From 5579d0b614a5271922b64bab347ba956345a8bce Mon Sep 17 00:00:00 2001 From: Alec Sammon Date: Wed, 3 Jul 2024 13:52:16 +0100 Subject: [PATCH] Fix embedded struct marshalling --- sheriff.go | 5 +++-- sheriff_test.go | 29 +++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/sheriff.go b/sheriff.go index c6d1995..d4ddd2f 100644 --- a/sheriff.go +++ b/sheriff.go @@ -121,7 +121,8 @@ func Marshal(options *Options, data interface{}) (interface{}, error) { field := t.Field(i) val := v.Field(i) - jsonTag, jsonOpts := parseTag(field.Tag.Get("json")) + jsonTagVal, jsonTagExists := field.Tag.Lookup("json") + jsonTag, jsonOpts := parseTag(jsonTagVal) // If no json tag is provided, use the field Name if jsonTag == "" { @@ -194,7 +195,7 @@ func Marshal(options *Options, data interface{}) (interface{}, error) { // when a composition field we want to bring the child // nodes to the top nestedVal, ok := v.(KVStore) - if isEmbeddedField && ok { + if !jsonTagExists && isEmbeddedField && ok { nestedVal.Each(func(k string, v interface{}) { dest.Set(k, v) }) diff --git a/sheriff_test.go b/sheriff_test.go index 72b5a62..6801fad 100644 --- a/sheriff_test.go +++ b/sheriff_test.go @@ -579,14 +579,20 @@ type TestMarshal_Embedded struct { Foo string `json:"foo" groups:"test"` } +type TestMarshal_NamedEmbedded struct { + Qux string `json:"qux" groups:"test"` +} + type TestMarshal_EmbeddedParent struct { *TestMarshal_Embedded - Bar string `json:"bar" groups:"test"` + *TestMarshal_NamedEmbedded `json:"embedded"` + Bar string `json:"bar" groups:"test"` } func TestMarshal_EmbeddedField(t *testing.T) { v := TestMarshal_EmbeddedParent{ &TestMarshal_Embedded{"Hello"}, + &TestMarshal_NamedEmbedded{"Big"}, "World", } o := &Options{Groups: []string{"test"}} @@ -597,13 +603,24 @@ func TestMarshal_EmbeddedField(t *testing.T) { actual, err := json.Marshal(actualMap) assert.NoError(t, err) - expected, err := json.Marshal(map[string]interface{}{ - "bar": "World", - "foo": "Hello", + t.Run("should match the original json marshal", func(t *testing.T) { + expected, err := json.Marshal(v) + assert.NoError(t, err) + + assert.JSONEq(t, string(expected), string(actual)) }) - assert.NoError(t, err) - assert.Equal(t, string(expected), string(actual)) + t.Run("should match the expected map", func(t *testing.T) { + expectedMap, err := json.Marshal(map[string]interface{}{ + "bar": "World", + "foo": "Hello", + "embedded": map[string]interface{}{ + "qux": "Big", + }, + }) + assert.NoError(t, err) + assert.JSONEq(t, string(expectedMap), string(actual)) + }) } type TestMarshal_EmbeddedEmpty struct {