Skip to content

Commit

Permalink
Do not delete key from unused map if field value cannot be set
Browse files Browse the repository at this point in the history
  • Loading branch information
mback2k committed Mar 19, 2020
1 parent 038ad38 commit 330a4f5
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 11 deletions.
6 changes: 3 additions & 3 deletions mapstructure.go
Expand Up @@ -1219,9 +1219,6 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
}
}

// Delete the key we're using from the unused map so we stop tracking
delete(dataValKeysUnused, rawMapKey.Interface())

if !fieldValue.IsValid() {
// This should never happen
panic("field is not valid")
Expand All @@ -1233,6 +1230,9 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
continue
}

// Delete the key we're using from the unused map so we stop tracking
delete(dataValKeysUnused, rawMapKey.Interface())

// If the name is empty string, then we're at the root, and we
// don't dot-join the fields.
if name != "" {
Expand Down
45 changes: 37 additions & 8 deletions mapstructure_test.go
Expand Up @@ -1019,6 +1019,31 @@ func TestDecoder_ErrorUnused(t *testing.T) {
}
}

func TestDecoder_ErrorUnused_NotSetable(t *testing.T) {
t.Parallel()

// lowercase vsilent is unexported and cannot be set
input := map[string]interface{}{
"vsilent": "false",
}

var result Basic
config := &DecoderConfig{
ErrorUnused: true,
Result: &result,
}

decoder, err := NewDecoder(config)
if err != nil {
t.Fatalf("err: %s", err)
}

err = decoder.Decode(input)
if err == nil {
t.Fatal("expected error")
}
}

func TestMap(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -1884,6 +1909,7 @@ func TestDecodeMetadata(t *testing.T) {
"vbar": map[string]interface{}{
"vstring": "foo",
"Vuint": 42,
"vsilent": "false",
"foo": "bar",
},
"bar": "nil",
Expand All @@ -1903,7 +1929,7 @@ func TestDecodeMetadata(t *testing.T) {
t.Fatalf("bad keys: %#v", md.Keys)
}

expectedUnused := []string{"Vbar.foo", "bar"}
expectedUnused := []string{"Vbar.vsilent", "Vbar.foo", "bar"}
if !reflect.DeepEqual(md.Unused, expectedUnused) {
t.Fatalf("bad unused: %#v", md.Unused)
}
Expand All @@ -1917,6 +1943,7 @@ func TestMetadata(t *testing.T) {
"vbar": map[string]interface{}{
"vstring": "foo",
"Vuint": 42,
"vsilent": "false",
"foo": "bar",
},
"bar": "nil",
Expand Down Expand Up @@ -1945,7 +1972,7 @@ func TestMetadata(t *testing.T) {
t.Fatalf("bad keys: %#v", md.Keys)
}

expectedUnused := []string{"Vbar.foo", "bar"}
expectedUnused := []string{"Vbar.vsilent", "Vbar.foo", "bar"}
if !reflect.DeepEqual(md.Unused, expectedUnused) {
t.Fatalf("bad unused: %#v", md.Unused)
}
Expand Down Expand Up @@ -2053,15 +2080,17 @@ func TestWeakDecodeMetadata(t *testing.T) {
t.Parallel()

input := map[string]interface{}{
"foo": "4",
"bar": "value",
"unused": "value",
"foo": "4",
"bar": "value",
"unused": "value",
"unexported": "value",
}

var md Metadata
var result struct {
Foo int
Bar string
Foo int
Bar string
unexported string
}

if err := WeakDecodeMetadata(input, &result, &md); err != nil {
Expand All @@ -2080,7 +2109,7 @@ func TestWeakDecodeMetadata(t *testing.T) {
t.Fatalf("bad keys: %#v", md.Keys)
}

expectedUnused := []string{"unused"}
expectedUnused := []string{"unused", "unexported"}
if !reflect.DeepEqual(md.Unused, expectedUnused) {
t.Fatalf("bad unused: %#v", md.Unused)
}
Expand Down

0 comments on commit 330a4f5

Please sign in to comment.