github.com/vipernet-xyz/tm@v0.34.24/libs/json/encoder.go (about)

     1  package json
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"reflect"
    10  	"strconv"
    11  	"time"
    12  )
    13  
    14  var (
    15  	timeType            = reflect.TypeOf(time.Time{})
    16  	jsonMarshalerType   = reflect.TypeOf(new(json.Marshaler)).Elem()
    17  	jsonUnmarshalerType = reflect.TypeOf(new(json.Unmarshaler)).Elem()
    18  )
    19  
    20  // Marshal marshals the value as JSON, using Amino-compatible JSON encoding (strings for
    21  // 64-bit numbers, and type wrappers for registered types).
    22  func Marshal(v interface{}) ([]byte, error) {
    23  	buf := new(bytes.Buffer)
    24  	err := encode(buf, v)
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  	return buf.Bytes(), nil
    29  }
    30  
    31  // MarshalIndent marshals the value as JSON, using the given prefix and indentation.
    32  func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
    33  	bz, err := Marshal(v)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  	buf := new(bytes.Buffer)
    38  	err = json.Indent(buf, bz, prefix, indent)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  	return buf.Bytes(), nil
    43  }
    44  
    45  func encode(w io.Writer, v interface{}) error {
    46  	// Bare nil values can't be reflected, so we must handle them here.
    47  	if v == nil {
    48  		return writeStr(w, "null")
    49  	}
    50  	rv := reflect.ValueOf(v)
    51  
    52  	// If this is a registered type, defer to interface encoder regardless of whether the input is
    53  	// an interface or a bare value. This retains Amino's behavior, but is inconsistent with
    54  	// behavior in structs where an interface field will get the type wrapper while a bare value
    55  	// field will not.
    56  	if typeRegistry.name(rv.Type()) != "" {
    57  		return encodeReflectInterface(w, rv)
    58  	}
    59  
    60  	return encodeReflect(w, rv)
    61  }
    62  
    63  func encodeReflect(w io.Writer, rv reflect.Value) error {
    64  	if !rv.IsValid() {
    65  		return errors.New("invalid reflect value")
    66  	}
    67  
    68  	// Recursively dereference if pointer.
    69  	for rv.Kind() == reflect.Ptr {
    70  		if rv.IsNil() {
    71  			return writeStr(w, "null")
    72  		}
    73  		rv = rv.Elem()
    74  	}
    75  
    76  	// Convert times to UTC.
    77  	if rv.Type() == timeType {
    78  		rv = reflect.ValueOf(rv.Interface().(time.Time).Round(0).UTC())
    79  	}
    80  
    81  	// If the value implements json.Marshaler, defer to stdlib directly. Since we've already
    82  	// dereferenced, we try implementations with both value receiver and pointer receiver. We must
    83  	// do this after the time normalization above, and thus after dereferencing.
    84  	if rv.Type().Implements(jsonMarshalerType) {
    85  		return encodeStdlib(w, rv.Interface())
    86  	} else if rv.CanAddr() && rv.Addr().Type().Implements(jsonMarshalerType) {
    87  		return encodeStdlib(w, rv.Addr().Interface())
    88  	}
    89  
    90  	switch rv.Type().Kind() {
    91  	// Complex types must be recursively encoded.
    92  	case reflect.Interface:
    93  		return encodeReflectInterface(w, rv)
    94  
    95  	case reflect.Array, reflect.Slice:
    96  		return encodeReflectList(w, rv)
    97  
    98  	case reflect.Map:
    99  		return encodeReflectMap(w, rv)
   100  
   101  	case reflect.Struct:
   102  		return encodeReflectStruct(w, rv)
   103  
   104  	// 64-bit integers are emitted as strings, to avoid precision problems with e.g.
   105  	// Javascript which uses 64-bit floats (having 53-bit precision).
   106  	case reflect.Int64, reflect.Int:
   107  		return writeStr(w, `"`+strconv.FormatInt(rv.Int(), 10)+`"`)
   108  
   109  	case reflect.Uint64, reflect.Uint:
   110  		return writeStr(w, `"`+strconv.FormatUint(rv.Uint(), 10)+`"`)
   111  
   112  	// For everything else, defer to the stdlib encoding/json encoder
   113  	default:
   114  		return encodeStdlib(w, rv.Interface())
   115  	}
   116  }
   117  
   118  func encodeReflectList(w io.Writer, rv reflect.Value) error {
   119  	// Emit nil slices as null.
   120  	if rv.Kind() == reflect.Slice && rv.IsNil() {
   121  		return writeStr(w, "null")
   122  	}
   123  
   124  	// Encode byte slices as base64 with the stdlib encoder.
   125  	if rv.Type().Elem().Kind() == reflect.Uint8 {
   126  		// Stdlib does not base64-encode byte arrays, only slices, so we copy to slice.
   127  		if rv.Type().Kind() == reflect.Array {
   128  			slice := reflect.MakeSlice(reflect.SliceOf(rv.Type().Elem()), rv.Len(), rv.Len())
   129  			reflect.Copy(slice, rv)
   130  			rv = slice
   131  		}
   132  		return encodeStdlib(w, rv.Interface())
   133  	}
   134  
   135  	// Anything else we recursively encode ourselves.
   136  	length := rv.Len()
   137  	if err := writeStr(w, "["); err != nil {
   138  		return err
   139  	}
   140  	for i := 0; i < length; i++ {
   141  		if err := encodeReflect(w, rv.Index(i)); err != nil {
   142  			return err
   143  		}
   144  		if i < length-1 {
   145  			if err := writeStr(w, ","); err != nil {
   146  				return err
   147  			}
   148  		}
   149  	}
   150  	return writeStr(w, "]")
   151  }
   152  
   153  func encodeReflectMap(w io.Writer, rv reflect.Value) error {
   154  	if rv.Type().Key().Kind() != reflect.String {
   155  		return errors.New("map key must be string")
   156  	}
   157  
   158  	// nil maps are not emitted as nil, to retain Amino compatibility.
   159  
   160  	if err := writeStr(w, "{"); err != nil {
   161  		return err
   162  	}
   163  	writeComma := false
   164  	for _, keyrv := range rv.MapKeys() {
   165  		if writeComma {
   166  			if err := writeStr(w, ","); err != nil {
   167  				return err
   168  			}
   169  		}
   170  		if err := encodeStdlib(w, keyrv.Interface()); err != nil {
   171  			return err
   172  		}
   173  		if err := writeStr(w, ":"); err != nil {
   174  			return err
   175  		}
   176  		if err := encodeReflect(w, rv.MapIndex(keyrv)); err != nil {
   177  			return err
   178  		}
   179  		writeComma = true
   180  	}
   181  	return writeStr(w, "}")
   182  }
   183  
   184  func encodeReflectStruct(w io.Writer, rv reflect.Value) error {
   185  	sInfo := makeStructInfo(rv.Type())
   186  	if err := writeStr(w, "{"); err != nil {
   187  		return err
   188  	}
   189  	writeComma := false
   190  	for i, fInfo := range sInfo.fields {
   191  		frv := rv.Field(i)
   192  		if fInfo.hidden || (fInfo.omitEmpty && frv.IsZero()) {
   193  			continue
   194  		}
   195  
   196  		if writeComma {
   197  			if err := writeStr(w, ","); err != nil {
   198  				return err
   199  			}
   200  		}
   201  		if err := encodeStdlib(w, fInfo.jsonName); err != nil {
   202  			return err
   203  		}
   204  		if err := writeStr(w, ":"); err != nil {
   205  			return err
   206  		}
   207  		if err := encodeReflect(w, frv); err != nil {
   208  			return err
   209  		}
   210  		writeComma = true
   211  	}
   212  	return writeStr(w, "}")
   213  }
   214  
   215  func encodeReflectInterface(w io.Writer, rv reflect.Value) error {
   216  	// Get concrete value and dereference pointers.
   217  	for rv.Kind() == reflect.Ptr || rv.Kind() == reflect.Interface {
   218  		if rv.IsNil() {
   219  			return writeStr(w, "null")
   220  		}
   221  		rv = rv.Elem()
   222  	}
   223  
   224  	// Look up the name of the concrete type
   225  	name := typeRegistry.name(rv.Type())
   226  	if name == "" {
   227  		return fmt.Errorf("cannot encode unregistered type %v", rv.Type())
   228  	}
   229  
   230  	// Write value wrapped in interface envelope
   231  	if err := writeStr(w, fmt.Sprintf(`{"type":%q,"value":`, name)); err != nil {
   232  		return err
   233  	}
   234  	if err := encodeReflect(w, rv); err != nil {
   235  		return err
   236  	}
   237  	return writeStr(w, "}")
   238  }
   239  
   240  func encodeStdlib(w io.Writer, v interface{}) error {
   241  	// Doesn't stream the output because that adds a newline, as per:
   242  	// https://golang.org/pkg/encoding/json/#Encoder.Encode
   243  	blob, err := json.Marshal(v)
   244  	if err != nil {
   245  		return err
   246  	}
   247  	_, err = w.Write(blob)
   248  	return err
   249  }
   250  
   251  func writeStr(w io.Writer, s string) error {
   252  	_, err := w.Write([]byte(s))
   253  	return err
   254  }