Add ErrorUnused config where it is an error if there are unused keys
diff --git a/mapstructure.go b/mapstructure.go index 151741c..231df40 100644 --- a/mapstructure.go +++ b/mapstructure.go
@@ -11,12 +11,18 @@ "errors" "fmt" "reflect" + "sort" "strings" ) // DecoderConfig is the configuration that is used to create a new decoder // and allows customization of various aspects of decoding. type DecoderConfig struct { + // If ErrorUnused is true, then it is an error for there to exist + // keys in the original map that were unused in the decoding process + // (extra keys). + ErrorUnused bool + // Metadata is the struct that will contain extra metadata about // the decoding. If this is nil, then no metadata will be tracked. Metadata *Metadata @@ -372,6 +378,17 @@ } } + if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { + keys := make([]string, 0, len(dataValKeysUnused)) + for rawKey, _ := range dataValKeysUnused { + keys = append(keys, rawKey.(string)) + } + sort.Strings(keys) + + err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) + errors = appendErrors(errors, err) + } + if len(errors) > 0 { return &Error{errors} }
diff --git a/mapstructure_test.go b/mapstructure_test.go index cc1f249..b3e1363 100644 --- a/mapstructure_test.go +++ b/mapstructure_test.go
@@ -123,6 +123,31 @@ } } +func TestDecoder_ErrorUnused(t *testing.T) { + t.Parallel() + + input := map[string]interface{}{ + "vstring": "hello", + "foo": "bar", + } + + 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()