diff --git a/issue125_test.go b/issue125_test.go new file mode 100644 index 0000000..69cc894 --- /dev/null +++ b/issue125_test.go @@ -0,0 +1,37 @@ +package mergo + +import ( + "encoding/json" + "testing" +) + +var ( + data = `{"FirstSlice":[], "SecondSlice": null}` +) + +type settings struct { + FirstSlice []string `json:"FirstSlice"` + SecondSlice []string `json:"SecondSlice"` +} + +func TestIssue125MergeWithOverwrite(t *testing.T) { + + defaultSettings := settings{ + FirstSlice: []string{}, + SecondSlice: []string{}, + } + + var something settings + if err := json.Unmarshal([]byte(data), &something); err != nil { + t.Errorf("Error while Unmarshalling maprequest: %s", err) + } + if err := Merge(&something, defaultSettings, WithOverrideEmptySlice); err != nil { + t.Errorf("Error while merging: %s", err) + } + if something.FirstSlice == nil { + t.Error("Invalid merging first slice") + } + if something.SecondSlice == nil { + t.Error("Invalid merging second slice") + } +} diff --git a/merge.go b/merge.go index 7413dfc..3fb6c64 100644 --- a/merge.go +++ b/merge.go @@ -26,11 +26,12 @@ func hasExportedField(dst reflect.Value) (exported bool) { } type Config struct { - Overwrite bool - AppendSlice bool - TypeCheck bool - Transformers Transformers - overwriteWithEmptyValue bool + Overwrite bool + AppendSlice bool + TypeCheck bool + Transformers Transformers + overwriteWithEmptyValue bool + overwriteSliceWithEmptyValue bool } type Transformers interface { @@ -44,6 +45,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co overwrite := config.Overwrite typeCheck := config.TypeCheck overwriteWithEmptySrc := config.overwriteWithEmptyValue + overwriteSliceWithEmptySrc := config.overwriteSliceWithEmptyValue config.overwriteWithEmptyValue = false if !src.IsValid() { @@ -130,7 +132,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co dstSlice = reflect.ValueOf(dstElement.Interface()) } - if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { + if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { if typeCheck && srcSlice.Type() != dstSlice.Type() { return fmt.Errorf("cannot override two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type()) } @@ -159,7 +161,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co if !dst.CanSet() { break } - if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { + if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { dst.Set(src) } else if config.AppendSlice { if src.Type() != dst.Type() { @@ -244,6 +246,11 @@ func WithOverride(config *Config) { config.Overwrite = true } +// WithOverride will make merge override empty dst slice with empty src slice. +func WithOverrideEmptySlice(config *Config) { + config.overwriteSliceWithEmptyValue = true +} + // WithAppendSlice will make merge append slices instead of overwriting it. func WithAppendSlice(config *Config) { config.AppendSlice = true