This commit is contained in:
Matt Spaulding 2024-05-12 00:23:51 +02:00 committed by GitHub
commit 70f2c195e7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 73 additions and 0 deletions

View file

@ -33,6 +33,7 @@ import (
"sync"
"time"
"github.com/deckarep/golang-set"
"github.com/fsnotify/fsnotify"
"github.com/mitchellh/mapstructure"
slog "github.com/sagikazarmark/slog-shim"
@ -2076,6 +2077,32 @@ func (v *Viper) AllKeys() []string {
return a
}
// Get the set of all top level keys.
func TopLevelKeys() []string { return v.TopLevelKeys() }
func (v *Viper) TopLevelKeys() []string {
s := mapset.NewSetFromSlice(v.getMapKeys(castMapStringToMapInterface(v.aliases)))
s = s.Union(mapset.NewSetFromSlice(v.getMapKeys(v.override)))
s = s.Union(mapset.NewSetFromSlice(v.getMapKeys(castMapFlagToMapInterface(v.pflags))))
s = s.Union(mapset.NewSetFromSlice(v.getMapKeys(castMapStringToMapInterface(v.env))))
s = s.Union(mapset.NewSetFromSlice(v.getMapKeys(v.config)))
s = s.Union(mapset.NewSetFromSlice(v.getMapKeys(v.defaults)))
// convert interface{} to string
keys := []string{}
for _, k := range s.ToSlice() {
keys = append(keys, k.(string))
}
return keys
}
func (v *Viper) getMapKeys(m map[string]interface{}) []interface{} {
keys := []interface{}{}
for key := range m {
keys = append(keys, key)
}
return keys
}
// flattenAndMergeMap recursively flattens the given map into a map[string]bool
// of key paths (used as a set, easier to manipulate than a []string):
// - each path is merged into a single key string, delimited with v.keyDelim

View file

@ -52,6 +52,23 @@ var yamlExampleWithExtras = []byte(`Existing: true
Bogus: true
`)
var yamlTopLevelKeys = []byte(`
restuarants:
types:
sushi:
name: sushi2go
rating: 10
price: average
italian:
name: "pizza place"
rating: 7
price: average
thai:
name: "thai garden"
rating: 9
price: high
`)
type testUnmarshalExtra struct {
Existing bool
}
@ -864,6 +881,35 @@ func TestAllKeysWithEnv(t *testing.T) {
assert.ElementsMatch(t, []string{"id", "foo.bar"}, v.AllKeys())
}
func TestTopLevelKeys(t *testing.T) {
v := New()
v.SetConfigType("yaml")
r := bytes.NewReader(yamlTopLevelKeys)
err := v.ReadConfig(r)
assert.NoError(t, err)
fmt.Printf("%#v\n", v.config)
s := v.Sub("restuarants.types")
for _, i := range s.TopLevelKeys() {
ss := s.Sub(i)
switch i {
case "sushi":
assert.Equal(t, ss.GetString("name"), "sushi2go")
assert.Equal(t, ss.GetString("price"), "average")
assert.Equal(t, ss.GetInt("rating"), 10)
case "italian":
assert.Equal(t, ss.GetString("name"), "pizza place")
assert.Equal(t, ss.GetString("price"), "average")
assert.Equal(t, ss.GetInt("rating"), 7)
case "thai":
assert.Equal(t, ss.GetString("name"), "thai garden")
assert.Equal(t, ss.GetString("price"), "high")
assert.Equal(t, ss.GetInt("rating"), 9)
default:
t.Fatalf("unexpected key, %q", i)
}
}
}
func TestAliasesOfAliases(t *testing.T) {
v := New()
v.Set("Title", "Checking Case")