Merge pull request #45 from mitchellh/f-map-slice
Decode slice of maps to a single map in weak mode
diff --git a/mapstructure.go b/mapstructure.go
index 40be511..319a8b4 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -67,6 +67,7 @@
// FALSE, false, False. Anything else is an error)
// - empty array = empty map and vice versa
// - negative numbers to overflowed uint values (base 10)
+ // - slice of maps to a merged map
//
WeaklyTypedInput bool
@@ -456,15 +457,30 @@
// Check input type
dataVal := reflect.Indirect(reflect.ValueOf(data))
if dataVal.Kind() != reflect.Map {
- // Accept empty array/slice instead of an empty map in weakly typed mode
- if d.config.WeaklyTypedInput &&
- (dataVal.Kind() == reflect.Slice || dataVal.Kind() == reflect.Array) &&
- dataVal.Len() == 0 {
- val.Set(valMap)
- return nil
- } else {
- return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
+ // In weak mode, we accept a slice of maps as an input...
+ if d.config.WeaklyTypedInput {
+ switch dataVal.Kind() {
+ case reflect.Array, reflect.Slice:
+ // Special case for BC reasons (covered by tests)
+ if dataVal.Len() == 0 {
+ val.Set(valMap)
+ return nil
+ }
+
+ for i := 0; i < dataVal.Len(); i++ {
+ err := d.decode(
+ fmt.Sprintf("%s[%d]", name, i),
+ dataVal.Index(i).Interface(), val)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+ }
}
+
+ return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
}
// Accumulate errors
diff --git a/mapstructure_test.go b/mapstructure_test.go
index 8a27647..99fa5e0 100644
--- a/mapstructure_test.go
+++ b/mapstructure_test.go
@@ -771,6 +771,33 @@
}
}
+func TestSliceToMap(t *testing.T) {
+ t.Parallel()
+
+ input := []map[string]interface{}{
+ map[string]interface{}{
+ "foo": "bar",
+ },
+ map[string]interface{}{
+ "bar": "baz",
+ },
+ }
+
+ var result map[string]interface{}
+ err := WeakDecode(input, &result)
+ if err != nil {
+ t.Fatalf("got an error: %s", err)
+ }
+
+ expected := map[string]interface{}{
+ "foo": "bar",
+ "bar": "baz",
+ }
+ if !reflect.DeepEqual(result, expected) {
+ t.Errorf("bad: %#v", result)
+ }
+}
+
func TestInvalidType(t *testing.T) {
t.Parallel()