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"