mirror of https://github.com/spf13/viper.git
implementing a weak decode wrapper called UnmarshalExact that errors on non existant fields in the destination struct
This commit is contained in:
parent
dd66c894de
commit
c975dc1b4e
31
viper.go
31
viper.go
|
@ -623,6 +623,37 @@ func (v *Viper) Unmarshal(rawVal interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// A wrapper around mapstructure.Decode that mimics the WeakDecode functionality
|
||||
// while erroring on non existing vals in the destination struct
|
||||
func weakDecodeExact(input, output interface{}) error {
|
||||
config := &mapstructure.DecoderConfig{
|
||||
ErrorUnused: true,
|
||||
Metadata: nil,
|
||||
Result: output,
|
||||
WeaklyTypedInput: true,
|
||||
}
|
||||
|
||||
decoder, err := mapstructure.NewDecoder(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return decoder.Decode(input)
|
||||
}
|
||||
|
||||
// Unmarshals the config into a Struct, erroring if a field is non-existant
|
||||
// in the destination struct
|
||||
func (v *Viper) UnmarshalExact(rawVal interface{}) error {
|
||||
err := weakDecodeExact(v.AllSettings(), rawVal)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v.insensitiviseMaps()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Bind a full flag set to the configuration, using each flag's long
|
||||
// name as the config key.
|
||||
func BindPFlags(flags *pflag.FlagSet) (err error) { return v.BindPFlags(flags) }
|
||||
|
|
|
@ -37,6 +37,14 @@ eyes : brown
|
|||
beard: true
|
||||
`)
|
||||
|
||||
var yamlExampleWithExtras = []byte(`Existing: true
|
||||
Bogus: true
|
||||
`)
|
||||
|
||||
type testUnmarshalExtra struct {
|
||||
Existing bool
|
||||
}
|
||||
|
||||
var tomlExample = []byte(`
|
||||
title = "TOML Example"
|
||||
|
||||
|
@ -255,6 +263,18 @@ func TestUnmarshalling(t *testing.T) {
|
|||
assert.Equal(t, 35, Get("age"))
|
||||
}
|
||||
|
||||
func TestUnmarshalExact(t *testing.T) {
|
||||
vip := New()
|
||||
target := &testUnmarshalExtra{}
|
||||
vip.SetConfigType("yaml")
|
||||
r := bytes.NewReader(yamlExampleWithExtras)
|
||||
vip.ReadConfig(r)
|
||||
err := vip.UnmarshalExact(target)
|
||||
if err == nil {
|
||||
t.Fatal("UnmarshalExact should error when populating a struct from a conf that contains unused fields")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOverrides(t *testing.T) {
|
||||
Set("age", 40)
|
||||
assert.Equal(t, 40, Get("age"))
|
||||
|
@ -844,14 +864,14 @@ func TestUnmarshalingWithAliases(t *testing.T) {
|
|||
Set("name", "Steve")
|
||||
Set("lastname", "Owen")
|
||||
|
||||
RegisterAlias("UserID","Id")
|
||||
RegisterAlias("Firstname","name")
|
||||
RegisterAlias("Surname","lastname")
|
||||
RegisterAlias("UserID", "Id")
|
||||
RegisterAlias("Firstname", "name")
|
||||
RegisterAlias("Surname", "lastname")
|
||||
|
||||
type config struct {
|
||||
Id int
|
||||
Id int
|
||||
FirstName string
|
||||
Surname string
|
||||
Surname string
|
||||
}
|
||||
|
||||
var C config
|
||||
|
@ -862,4 +882,4 @@ func TestUnmarshalingWithAliases(t *testing.T) {
|
|||
}
|
||||
|
||||
assert.Equal(t, &C, &config{Id: 1, FirstName: "Steve", Surname: "Owen"})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue