diff --git a/api_test.go b/api_test.go index d0598a8..a0487d3 100644 --- a/api_test.go +++ b/api_test.go @@ -42,3 +42,25 @@ func TestInvalidMustCompilePanics(t *testing.T) { }() MustCompile("not a valid expression") } + +func TestToEntries(t *testing.T) { + assert := assert.New(t) + data := make(map[string]interface{}) + data["foo"] = "bar" + data["baz"] = 42 + result, err := Search("to_entries(@)", data) + assert.Nil(err) + + entries, ok := result.([]interface{}) + assert.True(ok) + assert.Equal(2, len(entries)) + + for _, entry := range entries { + entryMap, ok := entry.(map[string]interface{}) + assert.True(ok) + _, hasKey := entryMap["key"] + _, hasValue := entryMap["value"] + assert.True(hasKey) + assert.True(hasValue) + } +} diff --git a/compliance/functions.json b/compliance/functions.json index 8b8db36..417c98a 100644 --- a/compliance/functions.json +++ b/compliance/functions.json @@ -355,6 +355,18 @@ "expression": "values(foo)", "error": "invalid-type" }, + { + "expression": "to_entries(objects)", + "result": [{"key": "bar", "value": "baz"}, {"key": "foo", "value": "bar"}] + }, + { + "expression": "to_entries(empty_hash)", + "result": [] + }, + { + "expression": "to_entries(foo)", + "error": "invalid-type" + }, { "expression": "join(', ', strings)", "result": "a, b, c" diff --git a/functions.go b/functions.go index e9770e8..b5015a4 100644 --- a/functions.go +++ b/functions.go @@ -259,6 +259,13 @@ func newFunctionCaller() *functionCaller { }, handler: jpfValues, }, + "to_entries": { + name: "to_entries", + arguments: []argSpec{ + {types: []jpType{jpObject}}, + }, + handler: jpfToEntries, + }, "sort": { name: "sort", arguments: []argSpec{ @@ -711,6 +718,24 @@ func jpfValues(arguments []interface{}) (interface{}, error) { } return collected, nil } +func jpfToEntries(arguments []interface{}) (interface{}, error) { + arg := arguments[0].(map[string]interface{}) + keys := make([]string, 0, len(arg)) + for key := range arg { + keys = append(keys, key) + } + sort.Strings(keys) + + collected := make([]interface{}, 0, len(arg)) + for _, key := range keys { + entry := map[string]interface{}{ + "key": key, + "value": arg[key], + } + collected = append(collected, entry) + } + return collected, nil +} func jpfSort(arguments []interface{}) (interface{}, error) { if items, ok := toArrayNum(arguments[0]); ok { d := sort.Float64Slice(items)