diff --git a/structure.go b/structure.go index 589f7e2..d755151 100644 --- a/structure.go +++ b/structure.go @@ -134,7 +134,9 @@ func IsZero(s interface{}) bool { for _, field := range fields { val := v.FieldByName(field.Name) - if IsStruct(val.Interface()) { + _, tagOpts := parseTag(field.Tag.Get(DefaultTagName)) + + if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { ok := IsZero(val.Interface()) if !ok { return false @@ -171,7 +173,10 @@ func HasZero(s interface{}) bool { for _, field := range fields { val := v.FieldByName(field.Name) - if IsStruct(val.Interface()) { + + _, tagOpts := parseTag(field.Tag.Get(DefaultTagName)) + + if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { ok := HasZero(val.Interface()) if ok { return true diff --git a/structure_test.go b/structure_test.go index 5d14a3a..f3d1e51 100644 --- a/structure_test.go +++ b/structure_test.go @@ -548,6 +548,34 @@ func TestIsZero(t *testing.T) { } } +func TestIsZero_OmitNested(t *testing.T) { + type A struct { + Name string + D string + } + a := A{Name: "example"} + + type B struct { + A A `structure:",omitnested"` + C int + } + b := &B{A: a, C: 123} + + ok := IsZero(b) + if ok { + t.Error("IsZero should return false because A, B and C are initialized") + } + + aZero := A{} + bZero := &B{A: aZero} + + ok = IsZero(bZero) + if !ok { + t.Error("IsZero should return true because neither A nor B is initialized") + } + +} + func TestIsZero_Nested(t *testing.T) { type A struct { Name string @@ -647,6 +675,27 @@ func TestHasZero(t *testing.T) { } } +func TestHasZero_OmitNested(t *testing.T) { + type A struct { + Name string + D string + } + a := A{Name: "example"} + + type B struct { + A A `structure:",omitnested"` + C int + } + b := &B{A: a, C: 123} + + // Because the Field A inside B is omitted HasZero should return false + // because it will stop iterating deeper andnot going to lookup for D + ok := HasZero(b) + if ok { + t.Error("HasZero should return false because A and C are initialized") + } +} + func TestHasZero_Nested(t *testing.T) { type A struct { Name string diff --git a/tags.go b/tags.go index 5a3a8b0..c370af0 100644 --- a/tags.go +++ b/tags.go @@ -5,7 +5,7 @@ import "strings" // tagOptions contains a slice of tag options type tagOptions []string -// Has returns true if the given opt is available inside the slice. +// Has returns true if the given optiton is available in tagOptions func (t tagOptions) Has(opt string) bool { for _, tagOpt := range t { if tagOpt == opt {