|
|
- package json
-
- import (
- "bytes"
- "encoding/json"
- "errors"
- "fmt"
- "reflect"
- )
-
- // Unmarshal unmarshals JSON into the given value, using Amino-compatible JSON encoding (strings
- // for 64-bit numbers, and type wrappers for registered types).
- func Unmarshal(bz []byte, v interface{}) error {
- return decode(bz, v)
- }
-
- func decode(bz []byte, v interface{}) error {
- if len(bz) == 0 {
- return errors.New("cannot decode empty bytes")
- }
-
- rv := reflect.ValueOf(v)
- if rv.Kind() != reflect.Ptr {
- return errors.New("must decode into a pointer")
- }
- rv = rv.Elem()
-
- // If this is a registered type, defer to interface decoder regardless of whether the input is
- // an interface or a bare value. This retains Amino's behavior, but is inconsistent with
- // behavior in structs where an interface field will get the type wrapper while a bare value
- // field will not.
- if typeRegistry.name(rv.Type()) != "" {
- return decodeReflectInterface(bz, rv)
- }
-
- return decodeReflect(bz, rv)
- }
-
- func decodeReflect(bz []byte, rv reflect.Value) error {
- if !rv.CanAddr() {
- return errors.New("value is not addressable")
- }
-
- // Handle null for slices, interfaces, and pointers
- if bytes.Equal(bz, []byte("null")) {
- rv.Set(reflect.Zero(rv.Type()))
- return nil
- }
-
- // Dereference-and-construct pointers, to handle nested pointers.
- for rv.Kind() == reflect.Ptr {
- if rv.IsNil() {
- rv.Set(reflect.New(rv.Type().Elem()))
- }
- rv = rv.Elem()
- }
-
- // Times must be UTC and end with Z
- if rv.Type() == timeType {
- switch {
- case len(bz) < 2 || bz[0] != '"' || bz[len(bz)-1] != '"':
- return fmt.Errorf("JSON time must be an RFC3339 string, but got %q", bz)
- case bz[len(bz)-2] != 'Z':
- return fmt.Errorf("JSON time must be UTC and end with 'Z', but got %q", bz)
- }
- }
-
- // If value implements json.Umarshaler, call it.
- if rv.Addr().Type().Implements(jsonUnmarshalerType) {
- return rv.Addr().Interface().(json.Unmarshaler).UnmarshalJSON(bz)
- }
-
- switch rv.Type().Kind() {
- // Decode complex types recursively.
- case reflect.Slice, reflect.Array:
- return decodeReflectList(bz, rv)
-
- case reflect.Map:
- return decodeReflectMap(bz, rv)
-
- case reflect.Struct:
- return decodeReflectStruct(bz, rv)
-
- case reflect.Interface:
- return decodeReflectInterface(bz, rv)
-
- // For 64-bit integers, unwrap expected string and defer to stdlib for integer decoding.
- case reflect.Int64, reflect.Int, reflect.Uint64, reflect.Uint:
- if bz[0] != '"' || bz[len(bz)-1] != '"' {
- return fmt.Errorf("invalid 64-bit integer encoding %q, expected string", string(bz))
- }
- bz = bz[1 : len(bz)-1]
- fallthrough
-
- // Anything else we defer to the stdlib.
- default:
- return decodeStdlib(bz, rv)
- }
- }
-
- func decodeReflectList(bz []byte, rv reflect.Value) error {
- if !rv.CanAddr() {
- return errors.New("list value is not addressable")
- }
-
- switch rv.Type().Elem().Kind() {
- // Decode base64-encoded bytes using stdlib decoder, via byte slice for arrays.
- case reflect.Uint8:
- if rv.Type().Kind() == reflect.Array {
- var buf []byte
- if err := json.Unmarshal(bz, &buf); err != nil {
- return err
- }
- if len(buf) != rv.Len() {
- return fmt.Errorf("got %v bytes, expected %v", len(buf), rv.Len())
- }
- reflect.Copy(rv, reflect.ValueOf(buf))
-
- } else if err := decodeStdlib(bz, rv); err != nil {
- return err
- }
-
- // Decode anything else into a raw JSON slice, and decode values recursively.
- default:
- var rawSlice []json.RawMessage
- if err := json.Unmarshal(bz, &rawSlice); err != nil {
- return err
- }
- if rv.Type().Kind() == reflect.Slice {
- rv.Set(reflect.MakeSlice(reflect.SliceOf(rv.Type().Elem()), len(rawSlice), len(rawSlice)))
- }
- if rv.Len() != len(rawSlice) { // arrays of wrong size
- return fmt.Errorf("got list of %v elements, expected %v", len(rawSlice), rv.Len())
- }
- for i, bz := range rawSlice {
- if err := decodeReflect(bz, rv.Index(i)); err != nil {
- return err
- }
- }
- }
-
- // Replace empty slices with nil slices, for Amino compatibility
- if rv.Type().Kind() == reflect.Slice && rv.Len() == 0 {
- rv.Set(reflect.Zero(rv.Type()))
- }
-
- return nil
- }
-
- func decodeReflectMap(bz []byte, rv reflect.Value) error {
- if !rv.CanAddr() {
- return errors.New("map value is not addressable")
- }
-
- // Decode into a raw JSON map, using string keys.
- rawMap := make(map[string]json.RawMessage)
- if err := json.Unmarshal(bz, &rawMap); err != nil {
- return err
- }
- if rv.Type().Key().Kind() != reflect.String {
- return fmt.Errorf("map keys must be strings, got %v", rv.Type().Key().String())
- }
-
- // Recursively decode values.
- rv.Set(reflect.MakeMapWithSize(rv.Type(), len(rawMap)))
- for key, bz := range rawMap {
- value := reflect.New(rv.Type().Elem()).Elem()
- if err := decodeReflect(bz, value); err != nil {
- return err
- }
- rv.SetMapIndex(reflect.ValueOf(key), value)
- }
- return nil
- }
-
- func decodeReflectStruct(bz []byte, rv reflect.Value) error {
- if !rv.CanAddr() {
- return errors.New("struct value is not addressable")
- }
- sInfo := makeStructInfo(rv.Type())
-
- // Decode raw JSON values into a string-keyed map.
- rawMap := make(map[string]json.RawMessage)
- if err := json.Unmarshal(bz, &rawMap); err != nil {
- return err
- }
- for i, fInfo := range sInfo.fields {
- if !fInfo.hidden {
- frv := rv.Field(i)
- bz := rawMap[fInfo.jsonName]
- if len(bz) > 0 {
- if err := decodeReflect(bz, frv); err != nil {
- return err
- }
- } else if !fInfo.omitEmpty {
- frv.Set(reflect.Zero(frv.Type()))
- }
- }
- }
-
- return nil
- }
-
- func decodeReflectInterface(bz []byte, rv reflect.Value) error {
- if !rv.CanAddr() {
- return errors.New("interface value not addressable")
- }
-
- // Decode the interface wrapper.
- wrapper := interfaceWrapper{}
- if err := json.Unmarshal(bz, &wrapper); err != nil {
- return err
- }
- if wrapper.Type == "" {
- return errors.New("interface type cannot be empty")
- }
- if len(wrapper.Value) == 0 {
- return errors.New("interface value cannot be empty")
- }
-
- // Dereference-and-construct pointers, to handle nested pointers.
- for rv.Kind() == reflect.Ptr {
- if rv.IsNil() {
- rv.Set(reflect.New(rv.Type().Elem()))
- }
- rv = rv.Elem()
- }
-
- // Look up the interface type, and construct a concrete value.
- rt, returnPtr := typeRegistry.lookup(wrapper.Type)
- if rt == nil {
- return fmt.Errorf("unknown type %q", wrapper.Type)
- }
-
- cptr := reflect.New(rt)
- crv := cptr.Elem()
- if err := decodeReflect(wrapper.Value, crv); err != nil {
- return err
- }
-
- // This makes sure interface implementations with pointer receivers (e.g. func (c *Car)) are
- // constructed as pointers behind the interface. The types must be registered as pointers with
- // RegisterType().
- if rv.Type().Kind() == reflect.Interface && returnPtr {
- if !cptr.Type().AssignableTo(rv.Type()) {
- return fmt.Errorf("invalid type %q for this value", wrapper.Type)
- }
- rv.Set(cptr)
- } else {
- if !crv.Type().AssignableTo(rv.Type()) {
- return fmt.Errorf("invalid type %q for this value", wrapper.Type)
- }
- rv.Set(crv)
- }
- return nil
- }
-
- func decodeStdlib(bz []byte, rv reflect.Value) error {
- if !rv.CanAddr() && rv.Kind() != reflect.Ptr {
- return errors.New("value must be addressable or pointer")
- }
-
- // Make sure we are unmarshaling into a pointer.
- target := rv
- if rv.Kind() != reflect.Ptr {
- target = reflect.New(rv.Type())
- }
- if err := json.Unmarshal(bz, target.Interface()); err != nil {
- return err
- }
- rv.Set(target.Elem())
- return nil
- }
-
- type interfaceWrapper struct {
- Type string `json:"type"`
- Value json.RawMessage `json:"value"`
- }
|