Skip to content

Commit

Permalink
fix(marshal): omit fields tagged with "-"
Browse files Browse the repository at this point in the history
This is a behavior of json.Marshal() that should be emulated
  • Loading branch information
blgm committed May 22, 2020
1 parent ff76c24 commit 8367b06
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 9 deletions.
26 changes: 18 additions & 8 deletions internal/path/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ import (
"strings"
)

const omitEmptyToken string = "omitempty"
const (
omitEmptyToken string = "omitempty"
omitAlwaysToken string = "-"
)

type Segment struct {
Name string
List bool
}

type Path struct {
segments []Segment
OmitEmpty bool
segments []Segment
OmitEmpty bool
OmitAlways bool
}

func (p Path) Len() int {
Expand Down Expand Up @@ -44,11 +48,12 @@ func ComputePath(field reflect.StructField) Path {
var segments []Segment
name := field.Name
omitempty := false
omitalways := false

if tag := field.Tag.Get("json"); tag != "" {
name, omitempty = parseTag(tag, field.Name)
name, omitempty, omitalways = parseTag(tag, field.Name)
} else if tag := field.Tag.Get("jsonry"); tag != "" {
name, omitempty = parseTag(tag, field.Name)
name, omitempty, omitalways = parseTag(tag, field.Name)
segments = parseSegments(name)
}

Expand All @@ -60,12 +65,17 @@ func ComputePath(field reflect.StructField) Path {
}

return Path{
OmitEmpty: omitempty,
segments: segments,
OmitEmpty: omitempty,
OmitAlways: omitalways,
segments: segments,
}
}

func parseTag(tag, defaultName string) (name string, omitempty bool) {
func parseTag(tag, defaultName string) (name string, omitempty, omitalways bool) {
if tag == omitAlwaysToken {
return defaultName, false, true
}

parts := strings.Split(tag, ",")

if len(parts) >= 1 && len(parts[0]) > 0 {
Expand Down
22 changes: 22 additions & 0 deletions internal/path/path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,26 @@ var _ = Describe("Path", func() {
Expect(p.OmitEmpty).To(BeTrue())
})
})

Context("always omit", func() {
It("picks it up from a JSON tag", func() {
p := path.ComputePath(reflect.StructField{Tag: `json:"-"`})
Expect(p.OmitAlways).To(BeTrue())
})

It("picks it up from a JSONry tag", func() {
p := path.ComputePath(reflect.StructField{Tag: `jsonry:"-"`})
Expect(p.OmitAlways).To(BeTrue())
})

It("allows a literal name `-` from a JSON tag", func() {
p := path.ComputePath(reflect.StructField{Tag: `json:"-,"`})
Expect(p.OmitAlways).To(BeFalse())
})

It("allows a literal name `-` from a JSONry tag", func() {
p := path.ComputePath(reflect.StructField{Tag: `jsonry:"-,"`})
Expect(p.OmitAlways).To(BeFalse())
})
})
})
4 changes: 3 additions & 1 deletion marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ func marshalStruct(ctx context.Context, in reflect.Value) (map[string]interface{

if public(f) {
p := path.ComputePath(f)
if !p.OmitEmpty || !in.Field(i).IsZero() {
shouldSkip := p.OmitAlways || (p.OmitEmpty && in.Field(i).IsZero())

if !shouldSkip {
r, err := marshal(ctx.WithField(f.Name, f.Type), in.Field(i))
if err != nil {
return nil, err
Expand Down
16 changes: 16 additions & 0 deletions marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,22 @@ var _ = Describe("Marshal", func() {
})
})

Describe("omitting struct fields", func() {
It("omits struct fields tagged with `-`", func() {
type s struct {
A string `jsonry:"-"`
}
expectToMarshal(s{A: "foo"}, `{}`)
})

It("allows literal field name `-` ", func() {
type s struct {
A string `jsonry:"-,"`
}
expectToMarshal(s{A: "foo"}, `{"-":"foo"}`)
})
})

Describe("inputs", func() {
It("accept a struct", func() {
var s struct{}
Expand Down

0 comments on commit 8367b06

Please sign in to comment.