From ceb8c8a733a2925ca1c0816b6a304fdd9da0a7a6 Mon Sep 17 00:00:00 2001 From: Tao Wen Date: Tue, 7 Mar 2017 18:36:58 -0800 Subject: [PATCH] create map if nil --- feature_reflect.go | 4 +++- feature_reflect_object.go | 21 ++++++++++++--------- jsoniter_reflect_struct_test.go | 33 ++++++++++++++++++++++++--------- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/feature_reflect.go b/feature_reflect.go index a85a58e..b446812 100644 --- a/feature_reflect.go +++ b/feature_reflect.go @@ -200,7 +200,9 @@ func (decoder *mapDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { mapInterface.word = ptr realInterface := (*interface{})(unsafe.Pointer(&mapInterface)) realVal := reflect.ValueOf(*realInterface).Elem() - + if realVal.IsNil() { + realVal.Set(reflect.MakeMap(realVal.Type())) + } for field := iter.ReadObject(); field != ""; field = iter.ReadObject() { elem := reflect.New(decoder.elemType) decoder.elemDecoder.decode(unsafe.Pointer(elem.Pointer()), iter) diff --git a/feature_reflect_object.go b/feature_reflect_object.go index 2309dd0..be66575 100644 --- a/feature_reflect_object.go +++ b/feature_reflect_object.go @@ -33,14 +33,17 @@ func encoderOfStruct(typ reflect.Type) (Encoder, error) { fieldNames = []string{tagParts[0]} } } - encoder, err := encoderOfType(field.Type) - 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} + var encoder Encoder + if len(fieldNames) > 0 { + encoder, err := encoderOfType(field.Type) + 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 { @@ -85,7 +88,7 @@ func decoderOfStruct(typ reflect.Type) (Decoder, error) { fieldNames = []string{tagParts[0]} } } - if decoder == nil { + if decoder == nil && len(fieldNames) > 0 { var err error decoder, err = decoderOfType(field.Type) if err != nil { diff --git a/jsoniter_reflect_struct_test.go b/jsoniter_reflect_struct_test.go index 6cdb61e..d55edf8 100644 --- a/jsoniter_reflect_struct_test.go +++ b/jsoniter_reflect_struct_test.go @@ -3,6 +3,7 @@ package jsoniter import ( "testing" "github.com/json-iterator/go/require" + "bytes" ) func Test_decode_one_field_struct(t *testing.T) { @@ -88,15 +89,15 @@ func Test_decode_five_fields_struct(t *testing.T) { func Test_decode_ten_fields_struct(t *testing.T) { should := require.New(t) type TestObject struct { - field1 string - field2 string - field3 string - field4 string - field5 string - field6 string - field7 string - field8 string - field9 string + field1 string + field2 string + field3 string + field4 string + field5 string + field6 string + field7 string + field8 string + field9 string field10 string } obj := TestObject{} @@ -144,3 +145,17 @@ func Test_write_val_one_field_struct(t *testing.T) { should.Nil(err) should.Equal(`{"field-1":"hello"}`, str) } + +func Test_mixed(t *testing.T) { + should := require.New(t) + type AA struct { + ID int `json:"id"` + Payload map[string]interface{} `json:"payload"` + buf *bytes.Buffer `json:"-"` + } + aa := AA{} + err := UnmarshalFromString(` {"id":1, "payload":{"account":"123","password":"456"}}`, &aa) + should.Nil(err) + should.Equal(1, aa.ID) + should.Equal("123", aa.Payload["account"]) +} \ No newline at end of file