You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

278 lines
7.3 KiB

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"`
}