implementing a weak decode wrapper called UnmarshalExact that errors on non existant fields in the destination struct
diff --git a/viper.go b/viper.go
index a056e61..7a49a0a 100644
--- a/viper.go
+++ b/viper.go
@@ -623,6 +623,37 @@
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) }
diff --git a/viper_test.go b/viper_test.go
index ebde5ba..858caff 100644
--- a/viper_test.go
+++ b/viper_test.go
@@ -37,6 +37,14 @@
beard: true
`)
+var yamlExampleWithExtras = []byte(`Existing: true
+Bogus: true
+`)
+
+type testUnmarshalExtra struct {
+ Existing bool
+}
+
var tomlExample = []byte(`
title = "TOML Example"
@@ -255,6 +263,18 @@
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 @@
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 @@
}
assert.Equal(t, &C, &config{Id: 1, FirstName: "Steve", Surname: "Owen"})
-}
\ No newline at end of file
+}