Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion builtin/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,11 @@ var Builtins = []*Function{
Name: "fromJSON",
Func: func(args ...any) (any, error) {
var v any
err := json.Unmarshal([]byte(args[0].(string)), &v)
jsonStr := args[0]
if strPtr, ok := jsonStr.(*string); ok {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Althoug this is a working solution, we need to understand why OpDeref was not added before calling fromJSON.

Compiler adds OpDeref for arguments before calling a function. But only if needed. Aperently the check is not perfect.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured out why. Builtins compilation just do not check for deref. So we ether make compiler more advance. Or make it via additional call.

jsonStr = *strPtr
}
err := json.Unmarshal([]byte(jsonStr.(string)), &v)
if err != nil {
return nil, err
}
Expand Down
52 changes: 52 additions & 0 deletions builtin/builtin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -638,3 +638,55 @@ func Test_int_unwraps_underlying_value(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, true, out)
}

func TestBuiltin_json(t *testing.T) {
t.Run("fromJSON/string", func(t *testing.T) {
env := map[string]any{
"json": `{"foo": "bar"}`,
}
program, err := expr.Compile(`fromJSON(json)`, expr.Env(env))
require.NoError(t, err)

out, err := expr.Run(program, env)
require.NoError(t, err)
assert.Equal(t, map[string]any{"foo": "bar"}, out)
})

t.Run("fromJSON/string pointer", func(t *testing.T) {
jsonString := `{"foo": "bar"}`
env := map[string]any{
"json": &jsonString,
}
program, err := expr.Compile(`fromJSON(json)`, expr.Env(env))
require.NoError(t, err)

out, err := expr.Run(program, env)
require.NoError(t, err)
assert.Equal(t, map[string]any{"foo": "bar"}, out)
})

t.Run("toJSON/object", func(t *testing.T) {
env := map[string]any{
"obj": map[string]any{"foo": "bar"},
}
program, err := expr.Compile(`toJSON(obj)`, expr.Env(env))
require.NoError(t, err)

out, err := expr.Run(program, env)
require.NoError(t, err)
assert.Equal(t, "{\n \"foo\": \"bar\"\n}", out)
})

t.Run("toJSON/object pointer", func(t *testing.T) {
obj := map[string]any{"foo": "bar"}
env := map[string]any{
"obj": &obj,
}
program, err := expr.Compile(`toJSON(obj)`, expr.Env(env))
require.NoError(t, err)

out, err := expr.Run(program, env)
require.NoError(t, err)
assert.Equal(t, "{\n \"foo\": \"bar\"\n}", out)
})
}
Loading