diff --git a/structure.go b/structure.go index 9eadd17..5200e23 100644 --- a/structure.go +++ b/structure.go @@ -34,7 +34,12 @@ func Map(s interface{}) map[string]interface{} { var finalVal interface{} - if IsStruct(val.Interface()) { + tagName, tagOpts := parseTag(field.Tag.Get(DefaultTagName)) + if tagName != "" { + name = tagName + } + + if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { // look out for embedded structs, and convert them to a // map[string]interface{} too finalVal = Map(val.Interface()) @@ -42,12 +47,6 @@ func Map(s interface{}) map[string]interface{} { finalVal = val.Interface() } - // override if the user passed a structure tag value - // ignore if the user passed the "-" value - if tag := field.Tag.Get(DefaultTagName); tag != "" { - name = tag - } - out[name] = finalVal } diff --git a/structure_test.go b/structure_test.go index 3707216..0ea3946 100644 --- a/structure_test.go +++ b/structure_test.go @@ -3,6 +3,7 @@ package structure import ( "reflect" "testing" + "time" ) func TestMapNonStruct(t *testing.T) { @@ -145,6 +146,37 @@ func TestMap_CustomTag(t *testing.T) { } +func TestMap_OmitNested(t *testing.T) { + type A struct { + Name string + Value string + Time time.Time `structure:",omitnested"` + } + a := A{Time: time.Now()} + + type B struct { + Desc string + A A + } + b := &B{A: a} + + m := Map(b) + + in, ok := m["A"].(map[string]interface{}) + if !ok { + t.Error("Map nested structs is not available in the map") + } + + // should not happen + if _, ok := in["Time"].(map[string]interface{}); ok { + t.Error("Map nested struct should omit recursiving parsing of Time") + } + + if _, ok := in["Time"].(time.Time); !ok { + t.Error("Map nested struct should stop parsing of Time at is current value") + } +} + func TestMap_Nested(t *testing.T) { type A struct { Name string diff --git a/tags.go b/tags.go index c096728..5a3a8b0 100644 --- a/tags.go +++ b/tags.go @@ -17,7 +17,8 @@ func (t tagOptions) Has(opt string) bool { } // parseTag splits a struct field's tag into its name and a list of options -// which comes after a name +// which comes after a name. A tag is in the form of: "name,option1,option2". +// The name can be neglectected. func parseTag(tag string) (string, tagOptions) { res := strings.Split(tag, ",")