diff --git a/koanf.go b/koanf.go index 92ac982..b4bae13 100644 --- a/koanf.go +++ b/koanf.go @@ -413,13 +413,16 @@ func (ko *Koanf) MapKeys(path string) []string { return out } - mp, ok := o.(map[string]any) - if !ok { + // A value set with Set() or by a Provider such as structs keeps its native + // map type, so the keys have to be read through reflection too. + rv := reflect.ValueOf(o) + if rv.Kind() != reflect.Map || rv.Type().Key().Kind() != reflect.String { return out } - out = make([]string, 0, len(mp)) - for k := range mp { - out = append(out, k) + + out = make([]string, 0, rv.Len()) + for _, k := range rv.MapKeys() { + out = append(out, k.String()) } sort.Strings(out) return out diff --git a/tests/koanf_test.go b/tests/koanf_test.go index f402572..a8d772e 100644 --- a/tests/koanf_test.go +++ b/tests/koanf_test.go @@ -1691,6 +1691,17 @@ func TestTypedGettersNativeMaps(t *testing.T) { } } +func TestMapKeysNativeMap(t *testing.T) { + assert := assert.New(t) + + k := koanf.New(delim) + assert.NoError(k.Load(confmap.Provider(map[string]any{ + "ints": map[string]int64{"a": 1, "b": 2}, + }, "."), nil)) + + assert.Equal([]string{"a", "b"}, k.MapKeys("ints"), "map keys mismatch for a natively-typed map") +} + // waitTimeout waits for the waitgroup for the specified max timeout. // Returns true if waiting timed out. func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {