1
0
mirror of https://github.com/json-iterator/go.git synced 2025-04-23 11:37:32 +02:00

Fix standard compatiblility

Non-nil but empty map with omitempty should be ignored.

Signed-off-by: Peng Gao <peng.gao.dut@gmail.com>
This commit is contained in:
Peng Gao 2017-10-27 00:27:58 +08:00
parent 06b2a7cf1d
commit 640251ab91
3 changed files with 43 additions and 4 deletions

View File

@ -18,3 +18,23 @@ func TestEncoderHasTrailingNewline(t *testing.T) {
stdenc.Encode(1)
should.Equal(stdbuf.Bytes(), buf.Bytes())
}
// Non-nil but empty map should be ignored.
func TestOmitempty(t *testing.T) {
o := struct {
A string `json:"a,omitempty"`
B string `json:"b,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
}{
A: "a",
B: "b",
Annotations: map[string]string{},
}
should := require.New(t)
var buf, stdbuf bytes.Buffer
enc := ConfigCompatibleWithStandardLibrary.NewEncoder(&buf)
enc.Encode(o)
stdenc := json.NewEncoder(&stdbuf)
stdenc.Encode(o)
should.Equal(string(stdbuf.Bytes()), string(buf.Bytes()))
}

View File

@ -130,10 +130,28 @@ func (encoder *optionalEncoder) EncodeInterface(val interface{}, stream *Stream)
}
func (encoder *optionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*unsafe.Pointer)(ptr)) == nil
}
type optionalMapEncoder struct {
valueEncoder ValEncoder
}
func (encoder *optionalMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if *((*unsafe.Pointer)(ptr)) == nil {
return true
stream.WriteNil()
} else {
encoder.valueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
}
return false
}
func (encoder *optionalMapEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *optionalMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
p := *((*unsafe.Pointer)(ptr))
return p == nil || encoder.valueEncoder.IsEmpty(p)
}
type placeholderEncoder struct {

View File

@ -280,9 +280,10 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
if len(fieldNames) > 0 && err != nil {
return nil, err
}
// map is stored as pointer in the struct
// map is stored as pointer in the struct,
// and treat nil or empty map as empty field
if encoder != nil && field.Type.Kind() == reflect.Map {
encoder = &optionalEncoder{encoder}
encoder = &optionalMapEncoder{encoder}
}
}
binding := &Binding{