diff --git a/dict.go b/dict.go index 4315b354..41913dc7 100644 --- a/dict.go +++ b/dict.go @@ -1,6 +1,9 @@ package sprig import ( + "fmt" + "reflect" + "dario.cat/mergo" "github.com/mitchellh/copystructure" ) @@ -37,11 +40,15 @@ func pluck(key string, d ...map[string]interface{}) []interface{} { return res } -func keys(dicts ...map[string]interface{}) []string { +func keys(dicts ...interface{}) []string { k := []string{} for _, dict := range dicts { - for key := range dict { - k = append(k, key) + m := reflect.ValueOf(dict) + if m.Kind() != reflect.Map { + continue + } + for _, key := range m.MapKeys() { + k = append(k, fmt.Sprint(key.Interface())) } } return k diff --git a/dict_test.go b/dict_test.go index c829daa5..d5952a05 100644 --- a/dict_test.go +++ b/dict_test.go @@ -82,6 +82,24 @@ func TestKeys(t *testing.T) { } } +func TestKeysWithTypedMaps(t *testing.T) { + // keys should work with maps whose value type is not interface{} (issue #455). + type item struct{ N int } + vars := map[string]interface{}{ + "structMap": map[string]item{"foo": {1}, "bar": {2}}, + "intMap": map[string]int{"a": 1, "b": 2}, + } + tests := map[string]string{ + `{{ keys .structMap | sortAlpha }}`: "[bar foo]", + `{{ keys .intMap | sortAlpha }}`: "[a b]", + } + for tpl, expect := range tests { + if err := runtv(tpl, expect, vars); err != nil { + t.Error(err) + } + } +} + func TestPick(t *testing.T) { tests := map[string]string{ `{{- $d := dict "one" 1 "two" 222222 }}{{ pick $d "two" | len -}}`: "1", diff --git a/docs/dicts.md b/docs/dicts.md index ef441a1b..06dc95ea 100644 --- a/docs/dicts.md +++ b/docs/dicts.md @@ -184,7 +184,8 @@ deepCopy $source | mergeOverwrite $dest ## keys The `keys` function will return a `list` of all of the keys in one or more `dict` -types. Since a dictionary is _unordered_, the keys will not be in a predictable order. +types. Any map type is accepted, not only `dict` (`map[string]interface{}`). +Since a dictionary is _unordered_, the keys will not be in a predictable order. They can be sorted with `sortAlpha`. ```