github.com/516108736/tendermint@v0.36.0/libs/json/structs.go (about) 1 package json 2 3 import ( 4 "fmt" 5 "reflect" 6 "strings" 7 "unicode" 8 9 tmsync "github.com/tendermint/tendermint/libs/sync" 10 ) 11 12 var ( 13 // cache caches struct info. 14 cache = newStructInfoCache() 15 ) 16 17 // structCache is a cache of struct info. 18 type structInfoCache struct { 19 tmsync.RWMutex 20 structInfos map[reflect.Type]*structInfo 21 } 22 23 func newStructInfoCache() *structInfoCache { 24 return &structInfoCache{ 25 structInfos: make(map[reflect.Type]*structInfo), 26 } 27 } 28 29 func (c *structInfoCache) get(rt reflect.Type) *structInfo { 30 c.RLock() 31 defer c.RUnlock() 32 return c.structInfos[rt] 33 } 34 35 func (c *structInfoCache) set(rt reflect.Type, sInfo *structInfo) { 36 c.Lock() 37 defer c.Unlock() 38 c.structInfos[rt] = sInfo 39 } 40 41 // structInfo contains JSON info for a struct. 42 type structInfo struct { 43 fields []*fieldInfo 44 } 45 46 // fieldInfo contains JSON info for a struct field. 47 type fieldInfo struct { 48 jsonName string 49 omitEmpty bool 50 hidden bool 51 } 52 53 // makeStructInfo generates structInfo for a struct as a reflect.Value. 54 func makeStructInfo(rt reflect.Type) *structInfo { 55 if rt.Kind() != reflect.Struct { 56 panic(fmt.Sprintf("can't make struct info for non-struct value %v", rt)) 57 } 58 if sInfo := cache.get(rt); sInfo != nil { 59 return sInfo 60 } 61 fields := make([]*fieldInfo, 0, rt.NumField()) 62 for i := 0; i < cap(fields); i++ { 63 frt := rt.Field(i) 64 fInfo := &fieldInfo{ 65 jsonName: frt.Name, 66 omitEmpty: false, 67 hidden: frt.Name == "" || !unicode.IsUpper(rune(frt.Name[0])), 68 } 69 o := frt.Tag.Get("json") 70 if o == "-" { 71 fInfo.hidden = true 72 } else if o != "" { 73 opts := strings.Split(o, ",") 74 if opts[0] != "" { 75 fInfo.jsonName = opts[0] 76 } 77 for _, o := range opts[1:] { 78 if o == "omitempty" { 79 fInfo.omitEmpty = true 80 } 81 } 82 } 83 fields = append(fields, fInfo) 84 } 85 sInfo := &structInfo{fields: fields} 86 cache.set(rt, sInfo) 87 return sInfo 88 }