mirror of
https://github.com/json-iterator/go.git
synced 2025-04-23 11:37:32 +02:00
support decode int key map
This commit is contained in:
parent
29dc1d407d
commit
af4982b22c
@ -510,7 +510,7 @@ func decoderOfMap(typ reflect.Type) (Decoder, error) {
|
||||
return nil, err
|
||||
}
|
||||
mapInterface := reflect.New(typ).Interface()
|
||||
return &mapDecoder{typ, typ.Elem(), decoder, extractInterface(mapInterface)}, nil
|
||||
return &mapDecoder{typ, typ.Key(), typ.Elem(), decoder, extractInterface(mapInterface)}, nil
|
||||
}
|
||||
|
||||
func extractInterface(val interface{}) emptyInterface {
|
||||
|
@ -5,10 +5,12 @@ import (
|
||||
"reflect"
|
||||
"encoding/json"
|
||||
"encoding"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type mapDecoder struct {
|
||||
mapType reflect.Type
|
||||
keyType reflect.Type
|
||||
elemType reflect.Type
|
||||
elemDecoder Decoder
|
||||
mapInterface emptyInterface
|
||||
@ -23,12 +25,43 @@ func (decoder *mapDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
if realVal.IsNil() {
|
||||
realVal.Set(reflect.MakeMap(realVal.Type()))
|
||||
}
|
||||
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
|
||||
iter.ReadObjectCB(func(iter *Iterator, keyStr string) bool{
|
||||
elem := reflect.New(decoder.elemType)
|
||||
decoder.elemDecoder.decode(unsafe.Pointer(elem.Pointer()), iter)
|
||||
// to put into map, we have to use reflection
|
||||
realVal.SetMapIndex(reflect.ValueOf(string([]byte(field))), elem.Elem())
|
||||
realVal.SetMapIndex(decodeMapKey(iter, keyStr, decoder.keyType), elem.Elem())
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func decodeMapKey(iter *Iterator, keyStr string, keyType reflect.Type) reflect.Value {
|
||||
switch {
|
||||
case keyType.Kind() == reflect.String:
|
||||
return reflect.ValueOf(keyStr)
|
||||
//case reflect.PtrTo(kt).Implements(textUnmarshalerType):
|
||||
// kv = reflect.New(v.Type().Key())
|
||||
// d.literalStore(item, kv, true)
|
||||
// kv = kv.Elem()
|
||||
default:
|
||||
switch keyType.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
n, err := strconv.ParseInt(keyStr, 10, 64)
|
||||
if err != nil || reflect.Zero(keyType).OverflowInt(n) {
|
||||
iter.reportError("read map key as int64", "read int64 failed")
|
||||
return reflect.ValueOf("")
|
||||
}
|
||||
return reflect.ValueOf(n).Convert(keyType)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
n, err := strconv.ParseUint(keyStr, 10, 64)
|
||||
if err != nil || reflect.Zero(keyType).OverflowUint(n) {
|
||||
iter.reportError("read map key as uint64", "read uint64 failed")
|
||||
return reflect.ValueOf("")
|
||||
}
|
||||
return reflect.ValueOf(n).Convert(keyType)
|
||||
}
|
||||
}
|
||||
iter.reportError("read map key", "json: Unexpected key type")
|
||||
return reflect.ValueOf("")
|
||||
}
|
||||
|
||||
type mapEncoder struct {
|
||||
|
@ -68,10 +68,17 @@ func Test_slice_of_map(t *testing.T) {
|
||||
should.Equal("2", val[0]["1"])
|
||||
}
|
||||
|
||||
func Test_write_int_key_map(t *testing.T) {
|
||||
func Test_encode_int_key_map(t *testing.T) {
|
||||
should := require.New(t)
|
||||
val := map[int]string{1: "2"}
|
||||
str, err := MarshalToString(val)
|
||||
should.Nil(err)
|
||||
should.Equal(`{"1":"2"}`, str)
|
||||
}
|
||||
|
||||
func Test_decode_int_key_map(t *testing.T) {
|
||||
should := require.New(t)
|
||||
var val map[int]string
|
||||
should.Nil(UnmarshalFromString(`{"1":"2"}`, &val))
|
||||
should.Equal(map[int]string{1: "2"}, val)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user