diff --git a/viper.go b/viper.go index 4f1580c..b77e682 100644 --- a/viper.go +++ b/viper.go @@ -865,27 +865,13 @@ func UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) e return v.UnmarshalKey(key, rawVal, opts...) } func (v *Viper) UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error { - lcaseKey := strings.ToLower(key) + err := decode(v.Get(key), defaultDecoderConfig(rawVal, opts...)) - // AllSettings returns settings from every sources merged into one tree - settings := v.AllSettings() - - keyParts := strings.Split(lcaseKey, v.keyDelim) - for i := 0; i < len(keyParts)-1; i++ { - if value, found := settings[keyParts[i]]; found { - if valueMap, ok := value.(map[string]interface{}); ok { - settings = valueMap - continue - } - // if the current value is not a map[string]interface{} we most likely reach a - // leaf and the key/path is wrong - return fmt.Errorf("unknown key %s", lcaseKey) - } else { - return fmt.Errorf("unknown key %s", lcaseKey) - } + if err != nil { + return err } - finalSetting := settings[keyParts[len(keyParts)-1]] - return decode(finalSetting, defaultDecoderConfig(rawVal, opts...)) + + return nil } // Unmarshal unmarshals the config into a Struct. Make sure that the tags diff --git a/viper_test.go b/viper_test.go index f41b413..5507a6d 100644 --- a/viper_test.go +++ b/viper_test.go @@ -1703,48 +1703,6 @@ func TestParseNested(t *testing.T) { assert.Equal(t, 200*time.Millisecond, items[0].Nested.Delay) } -func TestUnmarshalKey(t *testing.T) { - type testStruct struct { - Delay int `mapstructure:"delay" yaml:"delay"` - Port int `mapstructure:"port" yaml:"port"` - Host string `mapstructure:"host" yaml:"host"` - Items []string `mapstructure:"items" yaml:"items"` - } - - config := ` -level_1: - level_2: - port: 1234 - items: - - "test 1" -` - v := New() - v.SetDefault("level_1.level_2.delay", 50) - v.SetDefault("level_1.level_2.port", 9999) - v.SetDefault("level_1.level_2.host", "default") - v.SetDefault("level_1.level_2.items", []string{}) - - // Use env vars for some settings - v.BindEnv("level_1.level_2.host", "DD_TEST_HOST") - t.Setenv("DD_TEST_HOST", "dd.com") - - initConfig(v, "yaml", config) - - // manually overwrite some settings - v.Set("level_1.level_2.items", []string{"test_2", "test_3"}) - - data := testStruct{} - err := v.UnmarshalKey("level_1.level_2", &data) - if err != nil { - t.Fatalf("unable to decode into struct, %v", err) - } - - assert.Equal(t, 50, data.Delay) // value from defaults - assert.Equal(t, 1234, data.Port) // value from config - assert.Equal(t, "dd.com", data.Host) // value from env - assert.Equal(t, []string{"test_2", "test_3"}, data.Items) // value from Set() -} - func doTestCaseInsensitive(t *testing.T, typ, config string) { v := New() initConfig(v, typ, config)