This commit is contained in:
Kolbe Kegel 2017-08-23 06:49:56 +00:00 committed by GitHub
commit c892f2738f
2 changed files with 49 additions and 0 deletions

View file

@ -768,6 +768,7 @@ func decode(input interface{}, config *mapstructure.DecoderConfig) error {
// UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent // UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent
// in the destination struct. // in the destination struct.
func UnmarshalExact(rawVal interface{}) error { return v.UnmarshalExact(rawVal) }
func (v *Viper) UnmarshalExact(rawVal interface{}) error { func (v *Viper) UnmarshalExact(rawVal interface{}) error {
config := defaultDecoderConfig(rawVal) config := defaultDecoderConfig(rawVal)
config.ErrorUnused = true config.ErrorUnused = true
@ -782,6 +783,23 @@ func (v *Viper) UnmarshalExact(rawVal interface{}) error {
return nil return nil
} }
// UnmarshalKeyExact takes a single key and unmarshals it into a Struct, erroring if a field
// is nonexistent in the destination struct.
func UnmarshalKeyExact(key string, rawVal interface{}) error { return v.UnmarshalKeyExact(key, rawVal) }
func (v *Viper) UnmarshalKeyExact(key string, rawVal interface{}) error {
config := defaultDecoderConfig(rawVal)
config.ErrorUnused = true
err := decode(v.Get(key), config)
if err != nil {
return err
}
v.insensitiviseMaps()
return nil
}
// BindPFlags binds a full flag set to the configuration, using each flag's long // BindPFlags binds a full flag set to the configuration, using each flag's long
// name as the config key. // name as the config key.

View file

@ -287,6 +287,37 @@ func TestUnmarshalExact(t *testing.T) {
} }
} }
func TestUnmarshalKeyExact(t *testing.T) {
type duration struct {
Delay time.Duration
}
type item struct {
Name string
Delay time.Duration
Nested duration
}
config := `invalid_but_irrelevant=true
[[parent]]
error=true
delay="100ms"
[parent.nested]
delay="200ms"
`
initConfig("toml", config)
var items []item
err := v.UnmarshalKeyExact("parent", &items)
if err == nil {
t.Fatal("UnmarshalKeyExact should error when populating a struct from a conf that contains unused fields")
}
assert.Equal(t, 1, len(items))
assert.Equal(t, 100*time.Millisecond, items[0].Delay)
assert.Equal(t, 200*time.Millisecond, items[0].Nested.Delay)
}
func TestOverrides(t *testing.T) { func TestOverrides(t *testing.T) {
Set("age", 40) Set("age", 40)
assert.Equal(t, 40, Get("age")) assert.Equal(t, 40, Get("age"))