Fix AllSettings when some map keys contain the key delimiter

This commit is contained in:
Olivier Vielpeau 2018-11-07 22:11:30 +01:00
parent ae103d7e59
commit e89dd07ee4
2 changed files with 49 additions and 1 deletions

View file

@ -1736,7 +1736,22 @@ func (v *Viper) AllSettings() map[string]interface{} {
// check just in case anything changes // check just in case anything changes
continue continue
} }
path := strings.Split(k, v.keyDelim)
// Build key path by splitting the key by keyDelim and checking that the parent keys
// are actually set.
// Example use case:
// Ensures sure that, for the yaml conf "foo.bar: baz", and keyDelim ".":
// the generated path is []string{"foo.bar", "baz"}, instead of []string{"foo", "bar", "baz"}
path := []string{}
splitPath := strings.Split(k, v.keyDelim)
i := 0
for j := range splitPath {
if v.IsSet(strings.Join(splitPath[:j+1], v.keyDelim)) {
path = append(path, strings.Join(splitPath[i:j+1], v.keyDelim))
i = j + 1
}
}
lastKey := strings.ToLower(path[len(path)-1]) lastKey := strings.ToLower(path[len(path)-1])
deepestMap := deepSearch(m, path[0:len(path)-1]) deepestMap := deepSearch(m, path[0:len(path)-1])
// set innermost value // set innermost value

View file

@ -500,6 +500,39 @@ func TestAllKeysWithEnv(t *testing.T) {
assert.Equal(t, expectedKeys, keys) assert.Equal(t, expectedKeys, keys)
} }
func TestAllSettingsWithDelimiterInKeys(t *testing.T) {
exampleYaml := `Hacker: true
name: steve
hobbies:
- skate.boarding
- snowboarding
clothing.summer:
jacket: leather
pants:
size: large
clothing.winter:
jacket: wool
pants:
size: medium
`
v := New()
v.SetConfigType("yaml")
r := strings.NewReader(exampleYaml)
if err := v.unmarshalReader(r, v.config); err != nil {
panic(err)
}
expectedAll := map[string]interface{}{"hacker": true, "name": "steve", "hobbies": []interface{}{"skate.boarding", "snowboarding"}, "clothing.summer": map[string]interface{}{"jacket": "leather", "pants": map[string]interface{}{"size": "large"}}, "clothing.winter": map[string]interface{}{"jacket": "wool", "pants": map[string]interface{}{"size": "medium"}}}
expectedKeys := sort.StringSlice{"hacker", "name", "hobbies", "clothing.summer.jacket", "clothing.summer.pants.size", "clothing.winter.jacket", "clothing.winter.pants.size"}
expectedKeys.Sort()
keys := sort.StringSlice(v.AllKeys())
keys.Sort()
assert.Equal(t, expectedKeys, keys)
assert.Equal(t, expectedAll, v.AllSettings())
}
func TestAliasesOfAliases(t *testing.T) { func TestAliasesOfAliases(t *testing.T) {
Set("Title", "Checking Case") Set("Title", "Checking Case")
RegisterAlias("Foo", "Bar") RegisterAlias("Foo", "Bar")