瀏覽代碼

fix map[string]interface{} in struct

Tao Wen 8 年之前
父節點
當前提交
6880076b44
共有 6 個文件被更改,包括 42 次插入3 次删除
  1. 0 1
      feature_any_object.go
  2. 1 1
      feature_reflect_native.go
  3. 5 0
      feature_reflect_object.go
  4. 12 0
      jsoniter_array_test.go
  5. 1 1
      jsoniter_demo_test.go
  6. 23 0
      jsoniter_interface_test.go

+ 0 - 1
feature_any_object.go

@@ -569,7 +569,6 @@ func (any *objectAny) IterateObject() (func() (string, Any, bool), bool) {
 		var fieldValueAsAny Any
 		if i == len(cacheKeys) {
 			fieldName = any.val.Type().Field(i).Name
-			fmt.Println(fieldName)
 			cacheKeys = append(cacheKeys, fieldName)
 			fieldValue := any.val.Field(i)
 			if fieldValue.CanInterface() {

+ 1 - 1
feature_reflect_native.go

@@ -226,7 +226,7 @@ func (codec *interfaceCodec) encode(ptr unsafe.Pointer, stream *Stream) {
 }
 
 func (encoder *interfaceCodec) encodeInterface(val interface{}, stream *Stream) {
-	WriteToStream(val, stream, encoder)
+	stream.WriteVal(val)
 }
 
 type anyCodec struct {

+ 5 - 0
feature_reflect_object.go

@@ -37,6 +37,11 @@ func encoderOfStruct(typ reflect.Type) (Encoder, error) {
 		if err != nil {
 			return prefix(fmt.Sprintf("{%s}", field.Name)).addToEncoder(encoder, err)
 		}
+		// map is stored as pointer in the struct
+		// but if struct only has one map, it is inlined
+		if field.Type.Kind() == reflect.Map && typ.NumField() > 1 {
+			encoder = &optionalEncoder{field.Type, encoder}
+		}
 		for _, fieldName := range fieldNames {
 			if structEncoder_.firstField == nil {
 				structEncoder_.firstField = &structFieldEncoder{&field, fieldName, encoder}

+ 12 - 0
jsoniter_array_test.go

@@ -241,6 +241,18 @@ func Test_write_val_empty_array(t *testing.T) {
 	should.Equal("[]", str)
 }
 
+func Test_write_array_of_interface_in_struct(t *testing.T) {
+	should := require.New(t)
+	type TestObject struct {
+		Field []interface{}
+		Field2 string
+	}
+	val := TestObject{[]interface{}{1, 2}, ""}
+	str, err := MarshalToString(val)
+	should.Nil(err)
+	should.Equal(`{"Field":[1,2],"Field2":""}`, str)
+}
+
 func Benchmark_jsoniter_array(b *testing.B) {
 	b.ReportAllocs()
 	input := []byte(`[1,2,3,4,5,6,7,8,9]`)

+ 1 - 1
jsoniter_demo_test.go

@@ -36,4 +36,4 @@ func Test_iterator_and_bind_api(t *testing.T) {
 	iter.ReadVal(&user)
 	iter.ReadArray() // array end
 	fmt.Println(user)
-}
+}

+ 23 - 0
jsoniter_interface_test.go

@@ -22,6 +22,29 @@ func Test_write_map_of_interface(t *testing.T) {
 	should.Equal(`{"hello":"world"}`, str)
 }
 
+func Test_write_map_of_interface_in_struct(t *testing.T) {
+	type TestObject struct {
+		Field map[string]interface{}
+	}
+	should := require.New(t)
+	val := TestObject{map[string]interface{}{"hello":"world"}}
+	str, err := MarshalToString(val)
+	should.Nil(err)
+	should.Equal(`{"Field":{"hello":"world"}}`, str)
+}
+
+func Test_write_map_of_interface_in_struct_with_two_fields(t *testing.T) {
+	type TestObject struct {
+		Field map[string]interface{}
+		Field2 string
+	}
+	should := require.New(t)
+	val := TestObject{map[string]interface{}{"hello":"world"}, ""}
+	str, err := MarshalToString(val)
+	should.Nil(err)
+	should.Equal(`{"Field":{"hello":"world"},"Field2":""}`, str)
+}
+
 type MyInterface interface {
 	Hello() string
 }