mirror of
https://github.com/json-iterator/go.git
synced 2025-04-01 21:24:21 +02:00
fix #219 should check real value for empty instead of just the pointer for nested field
This commit is contained in:
parent
6dad2de6cc
commit
0ab880662f
@ -266,9 +266,9 @@ func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructD
|
|||||||
for _, binding := range structDescriptor.Fields {
|
for _, binding := range structDescriptor.Fields {
|
||||||
binding.levels = append([]int{i}, binding.levels...)
|
binding.levels = append([]int{i}, binding.levels...)
|
||||||
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
|
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
|
||||||
binding.Encoder = &OptionalEncoder{binding.Encoder}
|
binding.Encoder = &dereferenceEncoder{binding.Encoder}
|
||||||
binding.Encoder = &structFieldEncoder{&field, binding.Encoder, omitempty}
|
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}
|
binding.Decoder = &structFieldDecoder{&field, binding.Decoder}
|
||||||
embeddedBindings = append(embeddedBindings, binding)
|
embeddedBindings = append(embeddedBindings, binding)
|
||||||
}
|
}
|
||||||
|
@ -43,13 +43,13 @@ func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type deferenceDecoder struct {
|
type dereferenceDecoder struct {
|
||||||
// only to deference a pointer
|
// only to deference a pointer
|
||||||
valueType reflect.Type
|
valueType reflect.Type
|
||||||
valueDecoder ValDecoder
|
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 {
|
if *((*unsafe.Pointer)(ptr)) == nil {
|
||||||
//pointer to null, we have to allocate memory to hold the value
|
//pointer to null, we have to allocate memory to hold the value
|
||||||
value := reflect.New(decoder.valueType)
|
value := reflect.New(decoder.valueType)
|
||||||
@ -82,6 +82,26 @@ func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
|||||||
return *((*unsafe.Pointer)(ptr)) == nil
|
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 {
|
type optionalMapEncoder struct {
|
||||||
valueEncoder ValEncoder
|
valueEncoder ValEncoder
|
||||||
}
|
}
|
||||||
|
@ -158,6 +158,28 @@ func Test_ignore_field_on_not_valid_type(t *testing.T) {
|
|||||||
should.Equal(`{"field-1":"hello world"}`, str)
|
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) {
|
func Test_recursive_struct(t *testing.T) {
|
||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
type TestObject struct {
|
type TestObject struct {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user