diff --git a/mapstructure.go b/mapstructure.go index 9087fd96..22cfdf91 100644 --- a/mapstructure.go +++ b/mapstructure.go @@ -1259,11 +1259,14 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re case reflect.Slice: if deep { var childType reflect.Type - switch v.Type().Elem().Kind() { - case reflect.Struct: + elemType := v.Type().Elem() + // Recurse into slices of structs and slices of pointers to + // structs alike, so []*T maps the same way []T does. + if elemType.Kind() == reflect.Struct || + (elemType.Kind() == reflect.Ptr && elemType.Elem().Kind() == reflect.Struct) { childType = reflect.TypeOf(map[string]any{}) - default: - childType = v.Type().Elem() + } else { + childType = elemType } sType := reflect.SliceOf(childType) diff --git a/mapstructure_test.go b/mapstructure_test.go index baf40dfe..c6b3a416 100644 --- a/mapstructure_test.go +++ b/mapstructure_test.go @@ -3865,6 +3865,7 @@ func TestDecode_structArrayDeepMap(t *testing.T) { type SourceParent struct { ChildrenA []SourceChild `mapstructure:"children-a,deep"` ChildrenB *[]SourceChild `mapstructure:"children-b,deep"` + ChildrenC []*SourceChild `mapstructure:"children-c,deep"` } var target map[string]any @@ -3878,6 +3879,10 @@ func TestDecode_structArrayDeepMap(t *testing.T) { {String: "one"}, {String: "two"}, }, + ChildrenC: []*SourceChild{ + {String: "one"}, + {String: "two"}, + }, } if err := Decode(source, &target); err != nil { @@ -3893,6 +3898,10 @@ func TestDecode_structArrayDeepMap(t *testing.T) { {"some-string": "one"}, {"some-string": "two"}, }, + "children-c": []map[string]any{ + {"some-string": "one"}, + {"some-string": "two"}, + }, } if !reflect.DeepEqual(target, expected) {