diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2024-02-06 05:22:12 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2024-02-07 15:02:38 +0200 |
commit | 36d6b4e5549dc45baf890105de5ef487211f0144 (patch) | |
tree | 762f9eba621026e9bb7d8fd69107a4447783a45a /tests/function | |
parent | a5acaba537dab8e06be1197916acff86699aa5a3 (diff) |
Add experimental support for JSON value types
New types:
json
json_array
json_object
New functions:
$json.value_type(<json>)
$json.value_size(<json>)
$json.member_{name,value}(<json-member>)
$json.object_names(<json-object>)
$json.array_size(<json-array>)
$json.array_find(<json-array>, <json>)
$json.array_find_index(<json-array>, <json>)
$json.load(<path>)
$json.parse(<text>)
$json.serialize(<json>[, <indentation>])
For example, to load a JSON value from a file:
j = $json.load($src_base/board.json)
Or to construct it in a buildfile:
j = [json] one@1 two@([json] 2 3 4) three@([json] x@1 y@-1)
This can also be done incrementally with append/prepend:
j = [json_object]
j += one@1
j += two@([json] 2 3 4)
j += three@([json] x@1 y@-1)
Instead of using this JSON-like syntax, one can also specify valid JSON
input text:
j = [json] '{"one":1, "two":[2, 3, 4], "three":{"x":1, "y":-1}'
Besides the above set of functions, other handy ways to access components
in a JSON value are iteration and subscript. For example:
for m: $j
print $member_name($m) $member_value($m)
print ($j[three])
A subscript can be nested:
print ($j[two][1])
print ($j[three][x])
While a JSON value can be printed directly like any other value, the
representation will not be pretty-printed. As a result, for complex
JSON values, printing a serialized representation might be a more
readable option:
info $serialize($j)
Diffstat (limited to 'tests/function')
-rw-r--r-- | tests/function/builtin/testscript | 3 | ||||
-rw-r--r-- | tests/function/json/buildfile | 4 | ||||
-rw-r--r-- | tests/function/json/testscript | 224 |
3 files changed, 231 insertions, 0 deletions
diff --git a/tests/function/builtin/testscript b/tests/function/builtin/testscript index 88f802a..04e8bd8 100644 --- a/tests/function/builtin/testscript +++ b/tests/function/builtin/testscript @@ -53,6 +53,9 @@ $* <'print $empty(abc)' >'false' : name $* <'print $empty(abc cxx{foo})' >'false' : names $* <'print $empty([bool] false)' >'false' : bool + $* <'print $empty([json] null)' >'true' : json-null + $* <'print $empty([json] "[]")' >'true' : json-array + $* <'print $empty([json] "{}")' >'true' : json-object } : first-second diff --git a/tests/function/json/buildfile b/tests/function/json/buildfile new file mode 100644 index 0000000..45c60d2 --- /dev/null +++ b/tests/function/json/buildfile @@ -0,0 +1,4 @@ +# file : tests/function/json/buildfile +# license : MIT; see accompanying LICENSE file + +./: testscript $b diff --git a/tests/function/json/testscript b/tests/function/json/testscript new file mode 100644 index 0000000..f5fc671 --- /dev/null +++ b/tests/function/json/testscript @@ -0,0 +1,224 @@ +# file : tests/function/json/testscript +# license : MIT; see accompanying LICENSE file + +# See also tests in type/json/. + +.include ../../common.testscript + +: type +: +$* <<EOI >>EOO +print $value_type([json] ) +print $value_type([json] null) +print $value_type([json] true) +print $value_type([json] 123) +print $value_type([json] -123) +print $value_type([json] 123, true) +print $value_type([json] -123, true) +print $value_type([json] 1 2 3) +print $value_type([json] one@1 two@2 three@3) + +j = [json] one@1 two@2 three@3 +i = [uint64] 1 +m = ($j[$i]) +print $value_type($j[$i]) +print $value_type($m) +EOI +null +null +boolean +number +number +unsigned number +signed number +array +object +object +object +EOO + +: member +: +$* <<EOI >>EOO +j = [json] one@1 two@2 three@3 +i = [uint64] 1 +m = ($j[$i]) +print $member_name($j[$i]) $member_value($j[$i]) +print $member_name($m) $member_value($m) +for m: $j + print $member_name($m) $member_value($m) +EOI +two 2 +two 2 +one 1 +two 2 +three 3 +EOO + +: size +: +$* <<EOI >>EOO +print $size([json] null) +print $size([json] true) +print $size([json] 123) +print $size([json] abc) +print $size([string] ([json] abc)) # @@ Should be 3 (quoted, type hint). +print $size([json] 1 2 3) +print $size([json] one@1 two@2 three@3) +EOI +0 +1 +1 +1 +5 +3 +3 +EOO + +: find +: +$* <<EOI >>EOO +j = [json] 1 ([json] one@1 two@2) 2 true 3 null 4 abc -5 null ([json] 1 2 3) +print $find_index($j, null) +print $find_index($j, true) +print $find_index($j, 3) +print $find_index($j, 0x4) +print $find_index($j, -5) +print $find_index($j, abc) +print $find_index($j, [json] 1 2 3) +print $find_index($j, [json] two@2 one@1) +print $find_index($j, [json] 1 2) +print $find_index($j, [json] one@1) +print $find_index($j, [json] one@1 two@2 three@3) +print $find_index($j, [json] one@1 TWO@3) +print $find_index($j, [json] one@1 two@3) +EOI +5 +3 +4 +6 +8 +7 +10 +1 +11 +11 +11 +11 +11 +EOO + +: parse +: +{ + : basics + : + $* <<EOI >>EOO + print $json.parse('[123, "abc", {"one":1, "two":2}]') + EOI + [123,"abc",{"one":1,"two":2}] + EOO + + : diagnostics-invalid-input + : + $* <<EOI 2>>EOE != 0 + print $json.parse('{"one":, "two":2}]') + EOI + error: invalid json input: unexpected byte ',' in value + info: line 1, column 8, byte offset 8 + <stdin>:1:8: info: while calling json.parse(<untyped>) + EOE + + : diagnostics-duplicate-input + : + $* <<EOI 2>>EOE != 0 + print $json.parse('{"one":1, "one":2}]') + EOI + error: invalid json input: duplicate object member 'one' + info: line 1, column 11, byte offset 15 + <stdin>:1:8: info: while calling json.parse(<untyped>) + EOE +} + +: serialize +: +{ + : basics + : + $* <<EOI >>EOO + j = [json] 123 abc ([json] one@1 two@2) + print $json.serialize($j) + print $json.serialize($j, 0) + EOI + [ + 123, + "abc", + { + "one": 1, + "two": 2 + } + ] + [123,"abc",{"one":1,"two":2}] + EOO + + : diagnostics + : + if false + { + # This is not easy to trigger normally so we have a normally-disabled + # special hack in the $json.serialize() implementation to trigger this. + # + $* <<EOI 2>>EOE != 0 + print $json.serialize([json] deadbeef) + EOI + error: invalid json value: invalid UTF-8 text + info: while serializing string value + info: offending byte offset 4 + <stdin>:1:8: info: while calling json.serialize(json) + EOE + } + +} + +: load +: +{ + : basics + : + cat <<EOI >=input.json; + { + "str":"abc", + "num":123, + "arr":[1, 2, 3], + "obj":{"one":1, "two":2, "three":3} + } + EOI + $* <<EOI >>EOO + j = $json.load(input.json) + for m: $j + print $member_name($m) $member_value($m) + EOI + str "abc" + num 123 + arr [1,2,3] + obj {"one":1,"two":2,"three":3} + EOO + + : diagnostics + : + cat <<EOI >=input.json; + { + "str":"abc", + "num":, + "arr":[1, 2, 3], + "obj":{"one":1, "two":2, "three":3} + } + EOI + $* <<EOI 2>>EOE != 0 + j = $json.load(input.json) + EOI + input.json:3:9: error: invalid json input: unexpected byte ',' in value + info: byte offset 26 + <stdin>:1:6: info: while calling json.load(<untyped>) + EOE +} |