struct_field.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. package runtime
  2. import (
  3. "reflect"
  4. "strings"
  5. "unicode"
  6. )
  7. func getTag(field reflect.StructField) string {
  8. return field.Tag.Get("json")
  9. }
  10. func IsIgnoredStructField(field reflect.StructField) bool {
  11. if field.PkgPath != "" {
  12. if field.Anonymous {
  13. t := field.Type
  14. if t.Kind() == reflect.Ptr {
  15. t = t.Elem()
  16. }
  17. if t.Kind() != reflect.Struct {
  18. return true
  19. }
  20. } else {
  21. // private field
  22. return true
  23. }
  24. }
  25. tag := getTag(field)
  26. return tag == "-"
  27. }
  28. type StructTag struct {
  29. Key string
  30. IsTaggedKey bool
  31. IsOmitEmpty bool
  32. IsString bool
  33. Field reflect.StructField
  34. }
  35. type StructTags []*StructTag
  36. func (t StructTags) ExistsKey(key string) bool {
  37. for _, tt := range t {
  38. if tt.Key == key {
  39. return true
  40. }
  41. }
  42. return false
  43. }
  44. func isValidTag(s string) bool {
  45. if s == "" {
  46. return false
  47. }
  48. for _, c := range s {
  49. switch {
  50. case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
  51. // Backslash and quote chars are reserved, but
  52. // otherwise any punctuation chars are allowed
  53. // in a tag name.
  54. case !unicode.IsLetter(c) && !unicode.IsDigit(c):
  55. return false
  56. }
  57. }
  58. return true
  59. }
  60. func StructTagFromField(field reflect.StructField) *StructTag {
  61. keyName := field.Name
  62. tag := getTag(field)
  63. st := &StructTag{Field: field}
  64. opts := strings.Split(tag, ",")
  65. if len(opts) > 0 {
  66. if opts[0] != "" && isValidTag(opts[0]) {
  67. keyName = opts[0]
  68. st.IsTaggedKey = true
  69. }
  70. }
  71. st.Key = keyName
  72. if len(opts) > 1 {
  73. for _, opt := range opts[1:] {
  74. switch opt {
  75. case "omitempty":
  76. st.IsOmitEmpty = true
  77. case "string":
  78. st.IsString = true
  79. }
  80. }
  81. }
  82. return st
  83. }