From 80b007702ee6ce59d77e74e1ac160df8a246adcd Mon Sep 17 00:00:00 2001 From: sergeyt Date: Mon, 23 Nov 2015 01:41:40 +0600 Subject: [PATCH 1/2] fix nesting of time fields --- structs.go | 10 ++++++++-- structs_test.go | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/structs.go b/structs.go index a0b77e6..c3d3a4b 100644 --- a/structs.go +++ b/structs.go @@ -2,6 +2,7 @@ package structs import "reflect" +import "time" var ( // DefaultTagName is the default tag name for struct fields which provides @@ -89,7 +90,7 @@ func (s *Struct) Map() map[string]interface{} { } } - if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { + if IsStruct(val.Interface()) && !isTime(val.Interface()) && !tagOpts.Has("omitnested") { // look out for embedded structs, and convert them to a // map[string]interface{} too n := New(val.Interface()) @@ -148,7 +149,7 @@ func (s *Struct) Values() []interface{} { } } - if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { + if IsStruct(val.Interface()) && !isTime(val.Interface()) && !tagOpts.Has("omitnested") { // look out for embedded structs, and convert them to a // []interface{} to be added to the final values slice for _, embeddedVal := range Values(val.Interface()) { @@ -447,3 +448,8 @@ func IsStruct(s interface{}) bool { func Name(s interface{}) string { return New(s).Name() } + +func isTime(v interface{}) bool { + _, ok := v.(time.Time) + return ok +} diff --git a/structs_test.go b/structs_test.go index 14e3de7..43af9c8 100644 --- a/structs_test.go +++ b/structs_test.go @@ -296,6 +296,20 @@ func TestMap_Anonymous(t *testing.T) { } } +func TestMap_TimeField(t *testing.T) { + type A struct { + CreatedAt time.Time + } + + a := &A{CreatedAt: time.Now().UTC()} + m := Map(a) + + _, ok := m["CreatedAt"].(time.Time) + if !ok { + t.Error("Time field must be final") + } +} + func TestStruct(t *testing.T) { var T = struct{}{} From 77ad876ced82b02bfb81ecff5bdd8b5d1231aa74 Mon Sep 17 00:00:00 2001 From: sergeyt Date: Tue, 24 Nov 2015 20:12:59 +0600 Subject: [PATCH 2/2] updated the fix to avoid performance impact (PR #40) --- structs.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/structs.go b/structs.go index c3d3a4b..f3dcf9a 100644 --- a/structs.go +++ b/structs.go @@ -2,7 +2,6 @@ package structs import "reflect" -import "time" var ( // DefaultTagName is the default tag name for struct fields which provides @@ -90,12 +89,17 @@ func (s *Struct) Map() map[string]interface{} { } } - if IsStruct(val.Interface()) && !isTime(val.Interface()) && !tagOpts.Has("omitnested") { + if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { // look out for embedded structs, and convert them to a // map[string]interface{} too n := New(val.Interface()) n.TagName = s.TagName - finalVal = n.Map() + m := n.Map() + if len(m) == 0 { + finalVal = val.Interface() + } else { + finalVal = m + } } else { finalVal = val.Interface() } @@ -149,7 +153,7 @@ func (s *Struct) Values() []interface{} { } } - if IsStruct(val.Interface()) && !isTime(val.Interface()) && !tagOpts.Has("omitnested") { + if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { // look out for embedded structs, and convert them to a // []interface{} to be added to the final values slice for _, embeddedVal := range Values(val.Interface()) { @@ -448,8 +452,3 @@ func IsStruct(s interface{}) bool { func Name(s interface{}) string { return New(s).Name() } - -func isTime(v interface{}) bool { - _, ok := v.(time.Time) - return ok -}