introduce ZeroFields, starting to work with maps
This MIGHT introduce backwards incompatibities but we never meant for it
to work this way to begin with. Maps are now merged by default but you
can configure to zero them.
diff --git a/mapstructure.go b/mapstructure.go
index c5e33be..d3cb4e8 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -50,6 +50,11 @@
// (extra keys).
ErrorUnused bool
+ // ZeroFields, if set to true, will zero fields before writing them.
+ // For example, a map will be emptied before decoded values are put in
+ // it. If this is false, a map will be merged.
+ ZeroFields bool
+
// If WeaklyTypedInput is true, the decoder will make the following
// "weak" conversions:
//
@@ -438,9 +443,15 @@
valKeyType := valType.Key()
valElemType := valType.Elem()
- // Make a new map to hold our result
- mapType := reflect.MapOf(valKeyType, valElemType)
- valMap := reflect.MakeMap(mapType)
+ // By default we overwrite keys in the current map
+ valMap := val
+
+ // If the map is nil or we're purposely zeroing fields, make a new map
+ if valMap.IsNil() || d.config.ZeroFields {
+ // Make a new map to hold our result
+ mapType := reflect.MapOf(valKeyType, valElemType)
+ valMap = reflect.MakeMap(mapType)
+ }
// Check input type
dataVal := reflect.Indirect(reflect.ValueOf(data))
diff --git a/mapstructure_test.go b/mapstructure_test.go
index 1c24e3f..e05dcc6 100644
--- a/mapstructure_test.go
+++ b/mapstructure_test.go
@@ -517,6 +517,38 @@
}
}
+func TestMapMerge(t *testing.T) {
+ t.Parallel()
+
+ input := map[string]interface{}{
+ "vfoo": "foo",
+ "vother": map[interface{}]interface{}{
+ "foo": "foo",
+ "bar": "bar",
+ },
+ }
+
+ var result Map
+ result.Vother = map[string]string{"hello": "world"}
+ err := Decode(input, &result)
+ if err != nil {
+ t.Fatalf("got an error: %s", err)
+ }
+
+ if result.Vfoo != "foo" {
+ t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
+ }
+
+ expected := map[string]string{
+ "foo": "foo",
+ "bar": "bar",
+ "hello": "world",
+ }
+ if !reflect.DeepEqual(result.Vother, expected) {
+ t.Errorf("bad: %#v", result.Vother)
+ }
+}
+
func TestMapOfStruct(t *testing.T) {
t.Parallel()