Skip to content

Commit

Permalink
fix to_json builtin function bug (#138)
Browse files Browse the repository at this point in the history
  • Loading branch information
d5 authored Mar 13, 2019
1 parent b7977a4 commit 8707fd6
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 2 deletions.
7 changes: 6 additions & 1 deletion objects/builtin_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ func builtinToJSON(args ...Object) (Object, error) {
return nil, ErrWrongNumArguments
}

res, err := json.Marshal(objectToInterface(args[0]))
v := objectToInterface(args[0])
if vErr, isErr := v.(error); isErr {
v = vErr.Error()
}

res, err := json.Marshal(v)
if err != nil {
return &Error{Value: &String{Value: err.Error()}}, nil
}
Expand Down
15 changes: 15 additions & 0 deletions objects/conversion.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package objects

import (
"errors"
"fmt"
"strconv"
"time"
Expand Down Expand Up @@ -178,11 +179,25 @@ func objectToInterface(o Object) (res interface{}) {
for i, val := range o.Value {
res.([]interface{})[i] = objectToInterface(val)
}
case *ImmutableArray:
res = make([]interface{}, len(o.Value))
for i, val := range o.Value {
res.([]interface{})[i] = objectToInterface(val)
}
case *Map:
res = make(map[string]interface{})
for key, v := range o.Value {
res.(map[string]interface{})[key] = objectToInterface(v)
}
case *ImmutableMap:
res = make(map[string]interface{})
for key, v := range o.Value {
res.(map[string]interface{})[key] = objectToInterface(v)
}
case *Time:
res = o.Value
case *Error:
res = errors.New(o.String())
case Object:
return o
}
Expand Down
9 changes: 8 additions & 1 deletion runtime/vm_builtin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,24 @@ func TestBuiltinFunction(t *testing.T) {

// to_json
expect(t, `out = to_json(5)`, []byte("5"))
expect(t, `out = to_json("foobar")`, []byte(`"foobar"`))
expect(t, `out = to_json({foo: 5})`, []byte("{\"foo\":5}"))
expect(t, `out = to_json(immutable({foo: 5}))`, []byte("{\"foo\":5}"))
expect(t, `out = to_json([1,2,3])`, []byte("[1,2,3]"))
expect(t, `out = to_json(immutable([1,2,3]))`, []byte("[1,2,3]"))
expect(t, `out = to_json({foo: "bar"})`, []byte("{\"foo\":\"bar\"}"))
expect(t, `out = to_json({foo: 1.8})`, []byte("{\"foo\":1.8}"))
expect(t, `out = to_json({foo: true})`, []byte("{\"foo\":true}"))
expect(t, `out = to_json({foo: '8'})`, []byte("{\"foo\":56}"))
expect(t, `out = to_json({foo: bytes("foo")})`, []byte("{\"foo\":\"Zm9v\"}")) // json encoding returns []byte as base64 encoded string
expect(t, `out = to_json({foo: ["bar", 1, 1.8, '8', true]})`, []byte("{\"foo\":[\"bar\",1,1.8,56,true]}"))
expect(t, `out = to_json({foo: immutable(["bar", 1, 1.8, '8', true])})`, []byte("{\"foo\":[\"bar\",1,1.8,56,true]}"))
expect(t, `out = to_json({foo: [["bar", 1], ["bar", 1]]})`, []byte("{\"foo\":[[\"bar\",1],[\"bar\",1]]}"))
expect(t, `out = to_json({foo: {string: "bar", int: 1, float: 1.8, char: '8', bool: true}})`, []byte("{\"foo\":{\"bool\":true,\"char\":56,\"float\":1.8,\"int\":1,\"string\":\"bar\"}}"))
expect(t, `out = to_json({foo: immutable({string: "bar", int: 1, float: 1.8, char: '8', bool: true})})`, []byte("{\"foo\":{\"bool\":true,\"char\":56,\"float\":1.8,\"int\":1,\"string\":\"bar\"}}"))
expect(t, `out = to_json({foo: {map1: {string: "bar"}, map2: {int: "1"}}})`, []byte("{\"foo\":{\"map1\":{\"string\":\"bar\"},\"map2\":{\"int\":\"1\"}}}"))
expect(t, `out = to_json([["bar", 1], ["bar", 1]])`, []byte("[[\"bar\",1],[\"bar\",1]]"))
expect(t, `out = to_json(error("my error"))`, []byte(`"error: \"my error\""`))

// from_json
expect(t, `out = from_json("{\"foo\":5}").foo`, 5.0)
Expand All @@ -148,8 +155,8 @@ func TestBuiltinFunction(t *testing.T) {
expect(t, `out = from_json("{\"foo\":[[\"bar\",1],[\"bar\",1]]}").foo[0]`, ARR{"bar", 1.0})
expect(t, `out = from_json("{\"foo\":{\"bool\":true,\"char\":56,\"float\":1.8,\"int\":1,\"string\":\"bar\"}}").foo.bool`, true)
expect(t, `out = from_json("{\"foo\":{\"map1\":{\"string\":\"bar\"},\"map2\":{\"int\":\"1\"}}}").foo.map1.string`, "bar")

expect(t, `out = from_json("5")`, 5.0)
expect(t, `out = from_json("\"foobar\"")`, "foobar")
expect(t, `out = from_json("[\"bar\",1,1.8,56,true]")`, ARR{"bar", 1.0, 1.8, 56.0, true})

// sprintf
Expand Down

0 comments on commit 8707fd6

Please sign in to comment.