Quellcode durchsuchen

fix #219 should check real value for empty instead of just the pointer for nested field

Tao Wen vor 8 Jahren
Ursprung
Commit
0ab880662f
3 geänderte Dateien mit 46 neuen und 4 gelöschten Zeilen
  1. 2 2
      feature_reflect_extension.go
  2. 22 2
      feature_reflect_optional.go
  3. 22 0
      jsoniter_object_test.go

+ 2 - 2
feature_reflect_extension.go

@@ -266,9 +266,9 @@ func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructD
 				for _, binding := range structDescriptor.Fields {
 					binding.levels = append([]int{i}, binding.levels...)
 					omitempty := binding.Encoder.(*structFieldEncoder).omitempty
-					binding.Encoder = &OptionalEncoder{binding.Encoder}
+					binding.Encoder = &dereferenceEncoder{binding.Encoder}
 					binding.Encoder = &structFieldEncoder{&field, binding.Encoder, omitempty}
-					binding.Decoder = &deferenceDecoder{field.Type.Elem(), binding.Decoder}
+					binding.Decoder = &dereferenceDecoder{field.Type.Elem(), binding.Decoder}
 					binding.Decoder = &structFieldDecoder{&field, binding.Decoder}
 					embeddedBindings = append(embeddedBindings, binding)
 				}

+ 22 - 2
feature_reflect_optional.go

@@ -43,13 +43,13 @@ func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
 	}
 }
 
-type deferenceDecoder struct {
+type dereferenceDecoder struct {
 	// only to deference a pointer
 	valueType    reflect.Type
 	valueDecoder ValDecoder
 }
 
-func (decoder *deferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
+func (decoder *dereferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
 	if *((*unsafe.Pointer)(ptr)) == nil {
 		//pointer to null, we have to allocate memory to hold the value
 		value := reflect.New(decoder.valueType)
@@ -82,6 +82,26 @@ func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
 	return *((*unsafe.Pointer)(ptr)) == nil
 }
 
+type dereferenceEncoder struct {
+	ValueEncoder ValEncoder
+}
+
+func (encoder *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
+	if *((*unsafe.Pointer)(ptr)) == nil {
+		stream.WriteNil()
+	} else {
+		encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
+	}
+}
+
+func (encoder *dereferenceEncoder) EncodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
+func (encoder *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
+	return encoder.ValueEncoder.IsEmpty(*((*unsafe.Pointer)(ptr)))
+}
+
 type optionalMapEncoder struct {
 	valueEncoder ValEncoder
 }

+ 22 - 0
jsoniter_object_test.go

@@ -158,6 +158,28 @@ func Test_ignore_field_on_not_valid_type(t *testing.T) {
 	should.Equal(`{"field-1":"hello world"}`, str)
 }
 
+func Test_nested_field_omit_empty(t *testing.T) {
+	should := require.New(t)
+	type S1 struct {
+		F1 string `json:",omitempty"`
+	}
+
+	type S2 struct {
+		*S1
+		F2 string `json:",omitempty"`
+	}
+	s1 := &S1{
+		//F1: "abc",
+	}
+	s2 := &S2{
+		S1: s1,
+		F2: "123",
+	}
+	str, err := MarshalToString(s2)
+	should.Nil(err)
+	should.Equal(`{"F2":"123"}`, str)
+}
+
 func Test_recursive_struct(t *testing.T) {
 	should := require.New(t)
 	type TestObject struct {