func decodeInterfaceJSON(bz []byte) (name string, data []byte, err error) {
	dfw := new(disfixWrapper)
	err = json.Unmarshal(bz, dfw)
	if err != nil {
		err = fmt.Errorf("cannot parse disfix JSON wrapper: %v", err)
		return
	}
	if dfw.Name == "" {
		err = errors.New("JSON encoding of interfaces require non-empty type field.")
		return
	}
	name = dfw.Name
	if len(dfw.Data) == 0 {
		err = errors.New("interface JSON wrapper should have non-empty value field")
		return
	}
	data = dfw.Data
	return
}
decodeInterfaceJSON helps unravel the type name and
the stored data, which are expected in the form:
{
"type": "<canonical concrete type name>",
"value":  {}
}
package amino
import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"github.com/davecgh/go-spew/spew"
)
func (cdc *Codec) decodeReflectJSON(bz []byte, info *TypeInfo, rv reflect.Value, fopts FieldOptions) (err error) {
	if !rv.CanAddr() {
		panic("rv not addressable")
	}
	if info.Type.Kind() == reflect.Interface && rv.Kind() == reflect.Ptr {
		panic("should not happen")
	}
	if printLog {
		spew.Printf("(D) decodeReflectJSON(bz: %s, info: %v, rv: %#v (%v), fopts: %v)\n",
			bz, info, rv.Interface(), rv.Type(), fopts)
		defer func() {
			fmt.Printf("(D) -> err: %v\n", err)
		}()
	}
	if nullBytes(bz) {
		rv.Set(reflect.Zero(rv.Type()))
		return
	}
	for rv.Kind() == reflect.Ptr {
		if rv.IsNil() {
			newPtr := reflect.New(rv.Type().Elem())
			rv.Set(newPtr)
		}
		rv = rv.Elem()
	}
	if rv.Type() == timeType {
		if len(bz) >= 2 && bz[0] == '"' && bz[len(bz)-1] == '"' {
			if bz[len(bz)-2] != 'Z' {
				err = fmt.Errorf("Amino:JSON time must be UTC and end with 'Z' but got %s.", bz)
				return
			}
		} else {
			err = fmt.Errorf("Amino:JSON time must be an RFC3339Nano string, but got %s.", bz)
			return
		}
	}
	if rv.Addr().Type().Implements(jsonUnmarshalerType) {
		err = rv.Addr().Interface().(json.Unmarshaler).UnmarshalJSON(bz)
		return
	}
	if info.IsAminoUnmarshaler {
		rrv, rinfo := reflect.New(info.AminoUnmarshalReprType).Elem(), (*TypeInfo)(nil)
		rinfo, err = cdc.getTypeInfo_wlock(info.AminoUnmarshalReprType)
		if err != nil {
			return
		}
		err = cdc.decodeReflectJSON(bz, rinfo, rrv, fopts)
		if err != nil {
			return
		}
		uwrm := rv.Addr().MethodByName("UnmarshalAmino")
		uwouts := uwrm.Call([]reflect.Value{rrv})
		erri := uwouts[0].Interface()
		if erri != nil {
			err = erri.(error)
		}
		return
	}
	switch ikind := info.Type.Kind(); ikind {
	case reflect.Interface:
		err = cdc.decodeReflectJSONInterface(bz, info, rv, fopts)
	case reflect.Array:
		err = cdc.decodeReflectJSONArray(bz, info, rv, fopts)
	case reflect.Slice:
		err = cdc.decodeReflectJSONSlice(bz, info, rv, fopts)
	case reflect.Struct:
		err = cdc.decodeReflectJSONStruct(bz, info, rv, fopts)
	case reflect.Map:
		err = cdc.decodeReflectJSONMap(bz, info, rv, fopts)
	case reflect.Int64, reflect.Int:
		fallthrough
	case reflect.Uint64, reflect.Uint:
		if bz[0] != '"' || bz[len(bz)-1] != '"' {
			err = fmt.Errorf("invalid character -- Amino:JSON int/int64/uint/uint64 expects quoted values for javascript numeric support, got: %v.", string(bz))
			if err != nil {
				return
			}
		}
		bz = bz[1 : len(bz)-1]
		fallthrough
	case reflect.Int32, reflect.Int16, reflect.Int8,
		reflect.Uint32, reflect.Uint16, reflect.Uint8:
		err = invokeStdlibJSONUnmarshal(bz, rv, fopts)
	case reflect.Float32, reflect.Float64:
		if !fopts.Unsafe {
			return errors.New("Amino:JSON float* support requires `amino:\"unsafe\"`.")
		}
		fallthrough
	case reflect.Bool, reflect.String:
		err = invokeStdlibJSONUnmarshal(bz, rv, fopts)
	default:
		panic(fmt.Sprintf("unsupported type %v", info.Type.Kind()))
	}
	return
}
func invokeStdlibJSONUnmarshal(bz []byte, rv reflect.Value, fopts FieldOptions) error {
	if !rv.CanAddr() && rv.Kind() != reflect.Ptr {
		panic("rv not addressable nor pointer")
	}
	var rrv reflect.Value = rv
	if rv.Kind() != reflect.Ptr {
		rrv = reflect.New(rv.Type())
	}
	if err := json.Unmarshal(bz, rrv.Interface()); err != nil {
		return err
	}
	rv.Set(rrv.Elem())
	return nil
}
func (cdc *Codec) decodeReflectJSONInterface(bz []byte, iinfo *TypeInfo, rv reflect.Value, fopts FieldOptions) (err error) {
	if !rv.CanAddr() {
		panic("rv not addressable")
	}
	if printLog {
		fmt.Println("(d) decodeReflectJSONInterface")
		defer func() {
			fmt.Printf("(d) -> err: %v\n", err)
		}()
	}
	if !rv.IsNil() {
		rv.Set(iinfo.ZeroValue)
	}
	name, bz, err := decodeInterfaceJSON(bz)
	if err != nil {
		return
	}
	var cinfo *TypeInfo
	cinfo, err = cdc.getTypeInfoFromName_rlock(name)
	if err != nil {
		return
	}
	var crv, irvSet = constructConcreteType(cinfo)
	err = cdc.decodeReflectJSON(bz, cinfo, crv, fopts)
	if err != nil {
		rv.Set(irvSet)  
		return
	}
	rv.Set(irvSet)
	return
}
func (cdc *Codec) decodeReflectJSONArray(bz []byte, info *TypeInfo, rv reflect.Value, fopts FieldOptions) (err error) {
	if !rv.CanAddr() {
		panic("rv not addressable")
	}
	if printLog {
		fmt.Println("(d) decodeReflectJSONArray")
		defer func() {
			fmt.Printf("(d) -> err: %v\n", err)
		}()
	}
	ert := info.Type.Elem()
	length := info.Type.Len()
	switch ert.Kind() {
	case reflect.Uint8:  
		var buf []byte
		err = json.Unmarshal(bz, &buf)
		if err != nil {
			return
		}
		if len(buf) != length {
			err = fmt.Errorf("decodeReflectJSONArray: byte-length mismatch, got %v want %v",
				len(buf), length)
		}
		reflect.Copy(rv, reflect.ValueOf(buf))
		return
	default:  
		var einfo *TypeInfo
		einfo, err = cdc.getTypeInfo_wlock(ert)
		if err != nil {
			return
		}
		var rawSlice []json.RawMessage
		if err = json.Unmarshal(bz, &rawSlice); err != nil {
			return
		}
		if len(rawSlice) != length {
			err = fmt.Errorf("decodeReflectJSONArray: length mismatch, got %v want %v", len(rawSlice), length)
			return
		}
		for i := 0; i < length; i++ {
			erv := rv.Index(i)
			ebz := rawSlice[i]
			err = cdc.decodeReflectJSON(ebz, einfo, erv, fopts)
			if err != nil {
				return
			}
		}
		return
	}
}
func (cdc *Codec) decodeReflectJSONSlice(bz []byte, info *TypeInfo, rv reflect.Value, fopts FieldOptions) (err error) {
	if !rv.CanAddr() {
		panic("rv not addressable")
	}
	if printLog {
		fmt.Println("(d) decodeReflectJSONSlice")
		defer func() {
			fmt.Printf("(d) -> err: %v\n", err)
		}()
	}
	var ert = info.Type.Elem()
	switch ert.Kind() {
	case reflect.Uint8:  
		err = json.Unmarshal(bz, rv.Addr().Interface())
		if err != nil {
			return
		}
		if rv.Len() == 0 {
			rv.Set(info.ZeroValue)
		} else {
		}
		return
	default:  
		var einfo *TypeInfo
		einfo, err = cdc.getTypeInfo_wlock(ert)
		if err != nil {
			return
		}
		var rawSlice []json.RawMessage
		if err = json.Unmarshal(bz, &rawSlice); err != nil {
			return
		}
		var length = len(rawSlice)
		if length == 0 {
			rv.Set(info.ZeroValue)
			return
		}
		var esrt = reflect.SliceOf(ert)  
		var srv = reflect.MakeSlice(esrt, length, length)
		for i := 0; i < length; i++ {
			erv := srv.Index(i)
			ebz := rawSlice[i]
			err = cdc.decodeReflectJSON(ebz, einfo, erv, fopts)
			if err != nil {
				return
			}
		}
		rv.Set(srv)
		return
	}
}
func (cdc *Codec) decodeReflectJSONStruct(bz []byte, info *TypeInfo, rv reflect.Value, fopts FieldOptions) (err error) {
	if !rv.CanAddr() {
		panic("rv not addressable")
	}
	if printLog {
		fmt.Println("(d) decodeReflectJSONStruct")
		defer func() {
			fmt.Printf("(d) -> err: %v\n", err)
		}()
	}
	var rawMap = make(map[string]json.RawMessage)
	err = json.Unmarshal(bz, &rawMap)
	if err != nil {
		return
	}
	for _, field := range info.Fields {
		var frv = rv.Field(field.Index)
		var finfo *TypeInfo
		finfo, err = cdc.getTypeInfo_wlock(field.Type)
		if err != nil {
			return
		}
		var valueBytes = rawMap[field.JSONName]
		if len(valueBytes) == 0 {
			frv.Set(reflect.Zero(frv.Type()))
			continue
		}
		err = cdc.decodeReflectJSON(valueBytes, finfo, frv, fopts)
		if err != nil {
			return
		}
	}
	return nil
}
func (cdc *Codec) decodeReflectJSONMap(bz []byte, info *TypeInfo, rv reflect.Value, fopts FieldOptions) (err error) {
	if !rv.CanAddr() {
		panic("rv not addressable")
	}
	if printLog {
		fmt.Println("(d) decodeReflectJSONMap")
		defer func() {
			fmt.Printf("(d) -> err: %v\n", err)
		}()
	}
	var rawMap = make(map[string]json.RawMessage)
	err = json.Unmarshal(bz, &rawMap)
	if err != nil {
		return
	}
	var krt = rv.Type().Key()
	if krt.Kind() != reflect.String {
		err = fmt.Errorf("decodeReflectJSONMap: key type must be string")  
		return
	}
	var vinfo *TypeInfo
	vinfo, err = cdc.getTypeInfo_wlock(rv.Type().Elem())
	if err != nil {
		return
	}
	var mrv = reflect.MakeMapWithSize(rv.Type(), len(rawMap))
	for key, valueBytes := range rawMap {
		vrv := reflect.New(mrv.Type().Elem()).Elem()
		err = cdc.decodeReflectJSON(valueBytes, vinfo, vrv, fopts)
		if err != nil {
			return
		}
		krv := reflect.New(reflect.TypeOf("")).Elem()
		krv.SetString(key)
		mrv.SetMapIndex(krv, vrv)
	}
	rv.Set(mrv)
	return nil
}
type disfixWrapper struct {
	Name string          `json:"type"`
	Data json.RawMessage `json:"value"`
}