1
0
mirror of https://github.com/json-iterator/go.git synced 2025-03-23 21:09:11 +02:00

support map

This commit is contained in:
Tao Wen 2016-12-11 00:38:07 +08:00
parent aa42ac95c0
commit e427475e9c
2 changed files with 49 additions and 0 deletions

17
jsoniter_map_test.go Normal file
View File

@ -0,0 +1,17 @@
package jsoniter
import (
"testing"
"reflect"
"fmt"
)
func Test_read_map(t *testing.T) {
iter := ParseString(`{"hello": "world"}`)
m := map[string]string{"1": "2"}
iter.Read(&m)
if !reflect.DeepEqual(map[string]string{"1": "2", "hello": "world"}, m) {
fmt.Println(iter.Error)
t.Fatal(m)
}
}

View File

@ -295,6 +295,27 @@ func (decoder *structFieldDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
}
}
type mapDecoder struct {
mapType reflect.Type
elemType reflect.Type
elemDecoder Decoder
mapInterface emptyInterface
}
func (decoder *mapDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
// dark magic to cast unsafe.Pointer back to interface{} using reflect.Type
mapInterface := decoder.mapInterface
mapInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
realVal := reflect.ValueOf(*realInterface).Elem()
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
elem := reflect.New(decoder.elemType)
decoder.elemDecoder.decode(unsafe.Pointer(elem.Pointer()), iter)
realVal.SetMapIndex(reflect.ValueOf(field), elem.Elem())
}
}
type sliceDecoder struct {
sliceType reflect.Type
elemType reflect.Type
@ -582,6 +603,8 @@ func decoderOfPtr(type_ reflect.Type) (Decoder, error) {
return decoderOfStruct(type_)
case reflect.Slice:
return prefix("[slice]").addTo(decoderOfSlice(type_))
case reflect.Map:
return prefix("[map]").addTo(decoderOfMap(type_))
case reflect.Ptr:
return prefix("[optional]").addTo(decoderOfOptional(type_.Elem()))
default:
@ -703,3 +726,12 @@ func decoderOfSlice(type_ reflect.Type) (Decoder, error) {
}
return &sliceDecoder{type_, type_.Elem(), decoder}, nil
}
func decoderOfMap(type_ reflect.Type) (Decoder, error) {
decoder, err := decoderOfPtr(type_.Elem())
if err != nil {
return nil, err
}
mapInterface := reflect.New(type_).Interface()
return &mapDecoder{type_, type_.Elem(), decoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
}