struct_field.go 1.6 KB

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