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