Skip to content

Commit b7be83e

Browse files
authored
Add keys func (#533)
1 parent ced82e2 commit b7be83e

4 files changed

Lines changed: 83 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10-
- Nothing yet.
10+
### Added
11+
12+
- `keys` func that returns the keys or indices of a node. [See docs](https://daseldocs.tomwright.me/functions/keys).
1113

1214
## [v3.3.2] - 2026-03-18
1315

execution/func.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ var (
3131
FuncSum,
3232
FuncJoin,
3333
FuncReplace,
34+
FuncKeys,
3435
)
3536
)
3637

execution/func_keys.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package execution
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/tomwright/dasel/v3/model"
8+
)
9+
10+
// FuncKeys returns the keys of a map or the indices of a slice.
11+
var FuncKeys = NewFunc(
12+
"keys",
13+
func(ctx context.Context, data *model.Value, args model.Values) (*model.Value, error) {
14+
switch data.Type() {
15+
case model.TypeMap:
16+
keys, err := data.MapKeys()
17+
if err != nil {
18+
return nil, err
19+
}
20+
res := model.NewSliceValue()
21+
for _, key := range keys {
22+
if err := res.Append(model.NewStringValue(key)); err != nil {
23+
return nil, err
24+
}
25+
}
26+
return res, nil
27+
case model.TypeSlice:
28+
len, err := data.SliceLen()
29+
if err != nil {
30+
return nil, err
31+
}
32+
res := model.NewSliceValue()
33+
for i := 0; i < len; i++ {
34+
if err := res.Append(model.NewIntValue(int64(i))); err != nil {
35+
return nil, err
36+
}
37+
}
38+
return res, nil
39+
default:
40+
return nil, fmt.Errorf("keys can only be used on maps and slices")
41+
}
42+
},
43+
ValidateArgsExactly(0),
44+
)

execution/func_keys_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package execution_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/tomwright/dasel/v3/model"
7+
_ "github.com/tomwright/dasel/v3/parsing/json"
8+
)
9+
10+
func TestFuncKeys(t *testing.T) {
11+
t.Run("returns slice indices", testCase{
12+
s: `[1,2,3,4,5].keys()`,
13+
outFn: func() *model.Value {
14+
r := model.NewSliceValue()
15+
for i := 0; i < 5; i++ {
16+
if err := r.Append(model.NewIntValue(int64(i))); err != nil {
17+
panic(err)
18+
}
19+
}
20+
return r
21+
},
22+
}.run)
23+
t.Run("returns map keys", testCase{
24+
s: `{"a": 3, "b": 4, "c": 5}.keys()`,
25+
outFn: func() *model.Value {
26+
r := model.NewSliceValue()
27+
for _, key := range []string{"a", "b", "c"} {
28+
if err := r.Append(model.NewStringValue(key)); err != nil {
29+
panic(err)
30+
}
31+
}
32+
return r
33+
},
34+
}.run)
35+
}

0 commit comments

Comments
 (0)