Skip to content

Commit

Permalink
add push operation
Browse files Browse the repository at this point in the history
  • Loading branch information
can3p committed Apr 15, 2024
1 parent 844e948 commit 43da6e0
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Available operations:
| del(path) | delete a key |
| merge(path, value) | merge json value into the path. Only JSON values are allowed |
| pop(path) | remove last element from an array |
| push(path, value) | add new element to an array |

## Examples:

Expand Down
1 change: 1 addition & 0 deletions pkg/operations/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var operations = map[string]Operation{
"del": Delete,
"merge": Merge,
"pop": Pop,
"push": Push,
}

//nolint:govet
Expand Down
34 changes: 34 additions & 0 deletions pkg/operations/push.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package operations

import (
"github.com/can3p/sackmesser/pkg/traverse/types"
"github.com/pkg/errors"
)

func Push(root types.Node, path []types.PathElement, args ...any) error {
if len(args) != 1 {
return errors.Errorf("set operation expects one argument")
}

value := args[0]
node, lastChunk, err := traverseButOne(root, path)

if err != nil {
return err
}

val, err := node.GetField(lastChunk)

if err != nil {
return err
}

typed, ok := val.([]any)
if !ok {
return types.ErrWrongVisit
}

typed = append(typed, value)

return node.SetField(lastChunk, typed)
}
52 changes: 52 additions & 0 deletions pkg/operations/push_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package operations

import (
"testing"

"github.com/alecthomas/assert/v2"
"github.com/can3p/sackmesser/pkg/traverse/simplejson"
"github.com/can3p/sackmesser/pkg/traverse/types"
)

func TestPushOperation(t *testing.T) {
jstr := `{ "abc": [ 1, 2, 3 ] }`

examples := []struct {
description string
path []types.PathElement
expected string
arg any
isErr bool
}{
{
description: "push array item",
path: testPath("abc"),
arg: true,
expected: `{ "abc": [ 1, 2, 3, true ]}`,
},
{
description: "push into scalar",
path: testPath("abc", 0),
arg: true,
isErr: true,
},
}

for idx, ex := range examples {
node := simplejson.MustParse([]byte(jstr))

err := Push(node, ex.path, ex.arg)

if ex.isErr {
assert.Error(t, err, "[Ex %d - %s]", idx+1, ex.description)
continue
} else {
assert.NoError(t, err, "[Ex %d - %s]", idx+1, ex.description)
}

expected := simplejson.MustParse([]byte(ex.expected))

assert.Equal(t, expected.Value(), node.Value(), "[Ex %d - %s]", idx+1, ex.description)
}

}

0 comments on commit 43da6e0

Please sign in to comment.