forked from mirror/viper
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
|
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
|
// Bind a full flag set to the configuration, using each flag's long
|
||||||
// name as the config key.
|
// name as the config key.
|
||||||
func BindPFlags(flags *pflag.FlagSet) (err error) { return v.BindPFlags(flags) }
|
func BindPFlags(flags *pflag.FlagSet) (err error) { return v.BindPFlags(flags) }
|
||||||
|
|
|
@ -37,6 +37,14 @@ eyes : brown
|
||||||
beard: true
|
beard: true
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
var yamlExampleWithExtras = []byte(`Existing: true
|
||||||
|
Bogus: true
|
||||||
|
`)
|
||||||
|
|
||||||
|
type testUnmarshalExtra struct {
|
||||||
|
Existing bool
|
||||||
|
}
|
||||||
|
|
||||||
var tomlExample = []byte(`
|
var tomlExample = []byte(`
|
||||||
title = "TOML Example"
|
title = "TOML Example"
|
||||||
|
|
||||||
|
@ -255,6 +263,18 @@ func TestUnmarshalling(t *testing.T) {
|
||||||
assert.Equal(t, 35, Get("age"))
|
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) {
|
func TestOverrides(t *testing.T) {
|
||||||
Set("age", 40)
|
Set("age", 40)
|
||||||
assert.Equal(t, 40, Get("age"))
|
assert.Equal(t, 40, Get("age"))
|
||||||
|
@ -844,9 +864,9 @@ func TestUnmarshalingWithAliases(t *testing.T) {
|
||||||
Set("name", "Steve")
|
Set("name", "Steve")
|
||||||
Set("lastname", "Owen")
|
Set("lastname", "Owen")
|
||||||
|
|
||||||
RegisterAlias("UserID","Id")
|
RegisterAlias("UserID", "Id")
|
||||||
RegisterAlias("Firstname","name")
|
RegisterAlias("Firstname", "name")
|
||||||
RegisterAlias("Surname","lastname")
|
RegisterAlias("Surname", "lastname")
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
Id int
|
Id int
|
||||||
|
|
Loading…
Reference in New Issue