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()