Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix an issues where pointers were causing a key to be recorded twice #185

Merged
merged 1 commit into from Apr 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 8 additions & 7 deletions mapstructure.go
Expand Up @@ -378,6 +378,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e

var err error
outputKind := getKind(outVal)
addMetaKey := true
switch outputKind {
case reflect.Bool:
err = d.decodeBool(name, input, outVal)
Expand All @@ -396,7 +397,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
case reflect.Map:
err = d.decodeMap(name, input, outVal)
case reflect.Ptr:
err = d.decodePtr(name, input, outVal)
addMetaKey, err = d.decodePtr(name, input, outVal)
case reflect.Slice:
err = d.decodeSlice(name, input, outVal)
case reflect.Array:
Expand All @@ -410,7 +411,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e

// If we reached here, then we successfully decoded SOMETHING, so
// mark the key as used if we're tracking metainput.
if d.config.Metadata != nil && name != "" {
if addMetaKey && d.config.Metadata != nil && name != "" {
d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
}

Expand Down Expand Up @@ -861,7 +862,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
return nil
}

func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) error {
func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) {
// If the input data is nil, then we want to just set the output
// pointer to be nil as well.
isNil := data == nil
Expand All @@ -882,7 +883,7 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) er
val.Set(nilValue)
}

return nil
return true, nil
}

// Create an element of the concrete (non pointer) type and decode
Expand All @@ -896,16 +897,16 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) er
}

if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil {
return err
return false, err
}

val.Set(realVal)
} else {
if err := d.decode(name, data, reflect.Indirect(val)); err != nil {
return err
return false, err
}
}
return nil
return false, nil
}

func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error {
Expand Down
7 changes: 6 additions & 1 deletion mapstructure_test.go
Expand Up @@ -1939,6 +1939,11 @@ func TestDecodeMetadata(t *testing.T) {
func TestMetadata(t *testing.T) {
t.Parallel()

type testResult struct {
Vfoo string
Vbar BasicPointer
}

input := map[string]interface{}{
"vfoo": "foo",
"vbar": map[string]interface{}{
Expand All @@ -1951,7 +1956,7 @@ func TestMetadata(t *testing.T) {
}

var md Metadata
var result Nested
var result testResult
config := &DecoderConfig{
Metadata: &md,
Result: &result,
Expand Down