소스 검색

support map

Tao Wen 9 년 전
부모
커밋
e427475e9c
2개의 변경된 파일49개의 추가작업 그리고 0개의 파일을 삭제
  1. 17 0
      jsoniter_map_test.go
  2. 32 0
      jsoniter_reflect.go

+ 17 - 0
jsoniter_map_test.go

@@ -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)
+	}
+}

+ 32 - 0
jsoniter_reflect.go

@@ -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
+}