From 0c523920eb24d99e5706b1fd52a0007ba49370ec Mon Sep 17 00:00:00 2001 From: ronaudinho Date: Sun, 9 Oct 2022 17:23:37 +0000 Subject: [PATCH] Allow overriding non-map map element --- issue202_test.go | 138 +++++++++++++++++++++++++++++++++++++++++++++++ merge.go | 9 +++- 2 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 issue202_test.go diff --git a/issue202_test.go b/issue202_test.go new file mode 100644 index 0000000..df0620c --- /dev/null +++ b/issue202_test.go @@ -0,0 +1,138 @@ +package mergo_test + +import ( + "reflect" + "testing" + + "github.com/imdario/mergo" +) + +func TestIssue202(t *testing.T) { + tests := []struct { + name string + dst, src, want map[string]interface{} + }{ + { + name: "slice override string", + dst: map[string]interface{}{ + "x": 456, + "y": "foo", + }, + src: map[string]interface{}{ + "x": "123", + "y": []int{1, 2, 3}, + }, + want: map[string]interface{}{ + "x": "123", + "y": []int{1, 2, 3}, + }, + }, + { + name: "string override slice", + dst: map[string]interface{}{ + "x": 456, + "y": []int{1, 2, 3}, + }, + src: map[string]interface{}{ + "x": "123", + "y": "foo", + }, + want: map[string]interface{}{ + "x": "123", + "y": "foo", + }, + }, + { + name: "map override string", + dst: map[string]interface{}{ + "x": 456, + "y": "foo", + }, + src: map[string]interface{}{ + "x": "123", + "y": map[string]interface{}{ + "a": true, + }, + }, + want: map[string]interface{}{ + "x": "123", + "y": map[string]interface{}{ + "a": true, + }, + }, + }, + { + name: "string override map", + dst: map[string]interface{}{ + "x": 456, + "y": map[string]interface{}{ + "a": true, + }, + }, + src: map[string]interface{}{ + "x": "123", + "y": "foo", + }, + want: map[string]interface{}{ + "x": "123", + "y": "foo", + }, + }, + { + name: "map override map", + dst: map[string]interface{}{ + "x": 456, + "y": map[string]interface{}{ + "a": 10, + }, + }, + src: map[string]interface{}{ + "x": "123", + "y": map[string]interface{}{ + "a": true, + }, + }, + want: map[string]interface{}{ + "x": "123", + "y": map[string]interface{}{ + "a": true, + }, + }, + }, + { + name: "map override map with merge", + dst: map[string]interface{}{ + "x": 456, + "y": map[string]interface{}{ + "a": 10, + "b": 100, + }, + }, + src: map[string]interface{}{ + "x": "123", + "y": map[string]interface{}{ + "a": true, + }, + }, + want: map[string]interface{}{ + "x": "123", + "y": map[string]interface{}{ + "a": true, + "b": 100, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := mergo.Merge(&tt.dst, tt.src, mergo.WithOverride); err != nil { + t.Error(err) + } + + if !reflect.DeepEqual(tt.dst, tt.want) { + t.Errorf("maps not equal.\nwant:\n%v\ngot:\n%v\n", tt.want, tt.dst) + } + }) + } +} diff --git a/merge.go b/merge.go index 4b47d0b..8b43386 100644 --- a/merge.go +++ b/merge.go @@ -194,8 +194,13 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co dst.SetMapIndex(key, dstSlice) } } - if dstElement.IsValid() && !isEmptyValue(dstElement) && (reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map || reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Slice) { - continue + if dstElement.IsValid() && !isEmptyValue(dstElement) { + if reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Slice { + continue + } + if reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map && reflect.TypeOf(dstElement.Interface()).Kind() == reflect.Map { + continue + } } if srcElement.IsValid() && ((srcElement.Kind() != reflect.Ptr && overwrite) || !dstElement.IsValid() || isEmptyValue(dstElement)) {