diff --git a/mapstructure.go b/mapstructure.go index b384d9d9..72d5e307 100644 --- a/mapstructure.go +++ b/mapstructure.go @@ -894,6 +894,11 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re keyName = tagValue } + // This is an embedded struct pointer, handle it as a embedded struct below + if v.Kind() == reflect.Ptr && reflect.Indirect(v).Kind() == reflect.Struct { + v = reflect.Indirect(v) + } + switch v.Kind() { // this is an embedded struct, so handle it differently case reflect.Struct: diff --git a/mapstructure_test.go b/mapstructure_test.go index 63614e83..86ebb1b7 100644 --- a/mapstructure_test.go +++ b/mapstructure_test.go @@ -1352,6 +1352,41 @@ func TestNestedTypePointer(t *testing.T) { } } +func TestNestedTypeStructPointer(t *testing.T) { + t.Parallel() + + nestedInput := Basic{ + Vstring: "foo", + Vint: 42, + Vbool: true, + } + input := NestedPointer{ + Vfoo: "foo", + Vbar: &nestedInput, + } + + // nestedResult is validated in TestBasicTypes + nestedResult := map[string]interface{}{} + err := Decode(nestedInput, &nestedResult) + if err != nil { + t.Fatalf("got an err: %s", err.Error()) + } + + result := map[string]interface{}{} + err = Decode(input, &result) + if err != nil { + t.Fatalf("got an err: %s", err.Error()) + } + + expected := map[string]interface{}{ + "Vfoo": "foo", + "Vbar": nestedResult, + } + if !reflect.DeepEqual(result, expected) { + t.Errorf("bad: %#v", result) + } +} + // Test for issue #46. func TestNestedTypeInterface(t *testing.T) { t.Parallel() @@ -2316,7 +2351,7 @@ func TestDecode_StructTaggedWithOmitempty_KeepNonEmptyValues(t *testing.T) { VisibleMapField: nil, OmitMapField: map[string]interface{}{"k": "v"}, NestedField: nil, - OmitNestedField: &Nested{}, + OmitNestedField: nil, } var emptySlice []interface{} @@ -2334,7 +2369,6 @@ func TestDecode_StructTaggedWithOmitempty_KeepNonEmptyValues(t *testing.T) { "visible-map": emptyMap, "omittable-map": map[string]interface{}{"k": "v"}, "visible-nested": emptyNested, - "omittable-nested": &Nested{}, } actual := &map[string]interface{}{}