Skip to content

Commit

Permalink
update zero value handle
Browse files Browse the repository at this point in the history
  • Loading branch information
mralves committed Aug 7, 2019
1 parent 98a4a77 commit 6a56a97
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 16 deletions.
27 changes: 15 additions & 12 deletions json/encoder/struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,22 @@ func (changer *Struct) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
stream.WriteObjectStart()
numFields := v.NumField()
if numFields > 0 {
fv := v.Field(0)
ft := changer.Type.Field(0)
first := !changer.writeField(ft, fv, stream, true)
for i := 1; i < numFields; i++ {
lastWasWrote := false
for i := 0; i < numFields; i++ {
fv := v.Field(i)
ft := changer.Type.Field(i)
if changer.writeField(ft, fv, stream, first) {
first = false
}
lastWasWrote = changer.writeField(ft, fv, stream, lastWasWrote)
}
}
stream.WriteObjectEnd()
}
}

func (changer *Struct) writeField(structField reflect.StructField, value reflect.Value, stream *jsoniter.Stream, first bool) bool {
func (changer *Struct) writeField(structField reflect.StructField, value reflect.Value, stream *jsoniter.Stream, needsComma bool) bool {
if !value.CanInterface() {
return false
}
if !first {
if needsComma {
stream.WriteMore()
}
tag := strings.TrimSpace(structField.Tag.Get("json"))
Expand All @@ -71,16 +67,23 @@ func (changer *Struct) writeField(structField reflect.StructField, value reflect
pieces := strings.Split(tag, ",")
if len(pieces) > 1 {
if pieces[1] == "omitempty" {
isZero := func() (isZero bool) {
defer func() {
if recover() != nil {
isZero = false
}
}()
return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface())
}()
isNil := func() (isNil bool) {
defer func() {
if recover() != nil {
isNil = false
}
}()
isNil = value.IsNil()
return isNil
return value.IsNil()
}()
if isNil {
if isNil || isZero {
return false
}
}
Expand Down
14 changes: 10 additions & 4 deletions json/encoder/struct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,17 @@ func TestStruct_Encode(t *testing.T) {
t.Run("but the field is not empty", func(t *testing.T) {
t.Parallel()
is := assert.New(t)
v := 16
input := struct {
A int `json:"SuperParameter,omitempty"`
B int `json:"SuperParameterB"`
A int `json:"SuperParameterA"`
B *int `json:"SuperParameterB,omitempty"`
C int `json:"SuperParameterC,omitempty"`
D *int `json:"SuperParameterD,omitempty"`
E int `json:"SuperParameterE"`
}{
A: 15,
D: &v,
E: 17,
}
called := 0
subject := &Struct{
Expand All @@ -144,8 +150,8 @@ func TestStruct_Encode(t *testing.T) {
stream := jsoniter.NewStream(jsoniter.ConfigFastest, buf, 100)
subject.Encode(unsafe.Pointer(reflect.ValueOf(&input).Pointer()), stream)
stream.Flush()
is.Equal(`{"SUPERPARAMETER":15,"SUPERPARAMETERB":0}`, buf.String(), "it should change the name of the field")
is.Equal(2, called, "it should call the strategy exactly two times")
is.Equal(`{"SUPERPARAMETERA":15,"SUPERPARAMETERD":16,"SUPERPARAMETERE":17}`, buf.String(), "it should change the name of the field")
is.Equal(3, called, "it should call the strategy exactly three times")
})
t.Run("and the field is empty", func(t *testing.T) {
t.Parallel()
Expand Down

0 comments on commit 6a56a97

Please sign in to comment.