Skip to content

Commit

Permalink
Merge pull request #343 from tmm1/omit-emit-structs
Browse files Browse the repository at this point in the history
feat: apply omitEmptyFlag to empty structs
  • Loading branch information
vmihailenco committed Oct 1, 2023
2 parents 8a4375f + e5f8d03 commit 65e50f5
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 6 deletions.
2 changes: 1 addition & 1 deletion encode_map.go
Expand Up @@ -194,7 +194,7 @@ func encodeStructValue(e *Encoder, strct reflect.Value) error {
if e.flags&arrayEncodedStructsFlag != 0 || structFields.AsArray {
return encodeStructValueAsArray(e, strct, structFields.List)
}
fields := structFields.OmitEmpty(strct, e.flags&omitEmptyFlag != 0)
fields := structFields.OmitEmpty(e, strct)

if err := e.EncodeMapLen(len(fields)); err != nil {
return err
Expand Down
22 changes: 22 additions & 0 deletions msgpack_test.go
Expand Up @@ -420,6 +420,28 @@ func TestSetOmitEmpty(t *testing.T) {
err = dec.Decode(&t2)
require.Nil(t, err)
require.Nil(t, t2.Exported)

type Nested struct {
Foo string
Bar string
}
type Item struct {
X Nested
Y *Nested
}
i := Item{}
buf.Reset()
err = enc.Encode(i)
require.Nil(t, err)
require.NotContains(t, buf.Bytes(), byte('X'))
require.NotContains(t, buf.Bytes(), byte('Y'))

i = Item{Y: &Nested{}}
buf.Reset()
err = enc.Encode(i)
require.Nil(t, err)
require.NotContains(t, buf.Bytes(), byte('X'))
require.Contains(t, buf.Bytes(), byte('Y'))
}

type NullInt struct {
Expand Down
16 changes: 11 additions & 5 deletions types.go
Expand Up @@ -97,12 +97,13 @@ type field struct {
decoder decoderFunc
}

func (f *field) Omit(strct reflect.Value, forced bool) bool {
func (f *field) Omit(e *Encoder, strct reflect.Value) bool {
v, ok := fieldByIndex(strct, f.index)
if !ok {
return true
}
return (f.omitEmpty || forced) && isEmptyValue(v)
forced := e.flags&omitEmptyFlag != 0
return (f.omitEmpty || forced) && e.isEmptyValue(v)
}

func (f *field) EncodeValue(e *Encoder, strct reflect.Value) error {
Expand Down Expand Up @@ -152,15 +153,16 @@ func (fs *fields) warnIfFieldExists(name string) {
}
}

func (fs *fields) OmitEmpty(strct reflect.Value, forced bool) []*field {
func (fs *fields) OmitEmpty(e *Encoder, strct reflect.Value) []*field {
forced := e.flags&omitEmptyFlag != 0
if !fs.hasOmitEmpty && !forced {
return fs.List
}

fields := make([]*field, 0, len(fs.List))

for _, f := range fs.List {
if !f.Omit(strct, forced) {
if !f.Omit(e, strct) {
fields = append(fields, f)
}
}
Expand Down Expand Up @@ -317,7 +319,7 @@ type isZeroer interface {
IsZero() bool
}

func isEmptyValue(v reflect.Value) bool {
func (e *Encoder) isEmptyValue(v reflect.Value) bool {
kind := v.Kind()

for kind == reflect.Interface {
Expand All @@ -335,6 +337,10 @@ func isEmptyValue(v reflect.Value) bool {
switch kind {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Struct:
structFields := structs.Fields(v.Type(), e.structTag)
fields := structFields.OmitEmpty(e, v)
return len(fields) == 0
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
Expand Down

0 comments on commit 65e50f5

Please sign in to comment.