github.com/coveo/gotemplate@v2.7.7+incompatible/json/json.go (about) 1 package json 2 3 import ( 4 "encoding/json" 5 "math" 6 "reflect" 7 8 "github.com/coveo/gotemplate/collections" 9 "github.com/coveo/gotemplate/collections/implementation" 10 ) 11 12 // Expose json public objects 13 var ( 14 Compact = json.Compact 15 HTMLEscape = json.HTMLEscape 16 Indent = json.Indent 17 Marshal = json.Marshal 18 MarshalIndent = json.MarshalIndent 19 NewDecoder = json.NewDecoder 20 NewEncoder = json.NewEncoder 21 NativeUnmarshal = json.Unmarshal 22 ) 23 24 func (l jsonList) String() string { result, _ := Marshal(l.AsArray()); return string(result) } 25 func (d jsonDict) String() string { result, _ := Marshal(d.AsMap()); return string(result) } 26 27 func (l jsonList) PrettyPrint() string { 28 result, _ := MarshalIndent(l.AsArray(), "", " ") 29 return string(result) 30 } 31 32 func (d jsonDict) PrettyPrint() string { 33 result, _ := MarshalIndent(d.AsMap(), "", " ") 34 return string(result) 35 } 36 37 var _ = func() int { 38 collections.TypeConverters["!json"] = Unmarshal 39 return 0 40 }() 41 42 // Unmarshal calls the native Unmarshal but transform the results 43 // to returns Dictionary and GenerecList instead of go native collections. 44 func Unmarshal(data []byte, out interface{}) (err error) { 45 if err = NativeUnmarshal(data, out); err != nil { 46 return 47 } 48 transform(out) 49 return 50 } 51 52 func transform(out interface{}) { 53 result := transformElement(reflect.ValueOf(out).Elem().Interface()) 54 if _, isMap := out.(*map[string]interface{}); isMap { 55 // If the result is expected to be map[string]interface{}, we convert it back from internal dict type. 56 result = result.(jsonIDict).Native() 57 } 58 reflect.ValueOf(out).Elem().Set(reflect.ValueOf(result)) 59 } 60 61 func transformElement(source interface{}) interface{} { 62 if value, err := jsonHelper.TryAsDictionary(source); err == nil { 63 for _, key := range value.KeysAsString() { 64 value.Set(key, transformElement(value.Get(key))) 65 } 66 source = value 67 } else if value, err := jsonHelper.TryAsList(source); err == nil { 68 for i, sub := range value.AsArray() { 69 value.Set(i, transformElement(sub)) 70 } 71 source = value 72 } else if value, ok := source.(float64); ok { 73 // json.Unmarshal returns all int values as float64 74 if math.Floor(value) == value { 75 source = int(value) 76 } 77 } 78 return source 79 } 80 81 type ( 82 helperBase = implementation.BaseHelper 83 helperList = implementation.ListHelper 84 helperDict = implementation.DictHelper 85 ) 86 87 var needConversionImpl = implementation.NeedConversion 88 89 //go:generate genny -pkg=json -in=../collections/implementation/generic.go -out=generated_impl.go gen "ListTypeName=List DictTypeName=Dictionary base=json" 90 //go:generate genny -pkg=json -in=../collections/implementation/generic_test.go -out=generated_test.go gen "base=json"