Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 535 lines (481 sloc) 17.633 kb
4842019 @mdempsky first post
mdempsky authored
1 %% @author Bob Ippolito <bob@mochimedia.com>
2 %% @copyright 2006 Mochi Media, Inc.
3
4 %% @doc Yet another JSON (RFC 4627) library for Erlang.
5
6 -module(mochijson).
7 -author('bob@mochimedia.com').
8 -export([encoder/1, encode/1]).
9 -export([decoder/1, decode/1]).
10 -export([test/0]).
11
12 % This is a macro to placate syntax highlighters..
13 -define(Q, $\").
14 -define(ADV_COL(S, N), S#decoder{column=N+S#decoder.column}).
15 -define(INC_COL(S), S#decoder{column=1+S#decoder.column}).
16 -define(INC_LINE(S), S#decoder{column=1, line=1+S#decoder.line}).
17
18 %% @type iolist() = [char() | binary() | iolist()]
19 %% @type iodata() = iolist() | binary()
20 %% @type json_string() = atom | string() | binary()
21 %% @type json_number() = integer() | float()
22 %% @type json_array() = {array, [json_term()]}
23 %% @type json_object() = {struct, [{json_string(), json_term()}]}
24 %% @type json_term() = json_string() | json_number() | json_array() |
25 %% json_object()
26 %% @type encoding() = utf8 | unicode
27 %% @type encoder_option() = {input_encoding, encoding()} |
28 %% {handler, function()}
29 %% @type decoder_option() = {input_encoding, encoding()} |
30 %% {object_hook, function()}
31
32 -record(encoder, {input_encoding=unicode,
33 handler=null}).
34
35 -record(decoder, {input_encoding=utf8,
36 object_hook=null,
37 line=1,
38 column=1,
39 state=null}).
40
41 %% @spec encoder([encoder_option()]) -> function()
42 %% @doc Create an encoder/1 with the given options.
43 encoder(Options) ->
44 State = parse_encoder_options(Options, #encoder{}),
45 fun (O) -> json_encode(O, State) end.
46
47 %% @spec encode(json_term()) -> iolist()
48 %% @doc Encode the given as JSON to an iolist.
49 encode(Any) ->
50 json_encode(Any, #encoder{}).
51
52 %% @spec decoder([decoder_option()]) -> function()
53 %% @doc Create a decoder/1 with the given options.
54 decoder(Options) ->
55 State = parse_decoder_options(Options, #decoder{}),
56 fun (O) -> json_decode(O, State) end.
57
58 %% @spec decode(iolist()) -> json_term()
59 %% @doc Decode the given iolist to Erlang terms.
60 decode(S) ->
61 json_decode(S, #decoder{}).
62
63 test() ->
64 test_all().
65
66 %% Internal API
67
68 parse_encoder_options([], State) ->
69 State;
70 parse_encoder_options([{input_encoding, Encoding} | Rest], State) ->
71 parse_encoder_options(Rest, State#encoder{input_encoding=Encoding});
72 parse_encoder_options([{handler, Handler} | Rest], State) ->
73 parse_encoder_options(Rest, State#encoder{handler=Handler}).
74
75 parse_decoder_options([], State) ->
76 State;
77 parse_decoder_options([{input_encoding, Encoding} | Rest], State) ->
78 parse_decoder_options(Rest, State#decoder{input_encoding=Encoding});
79 parse_decoder_options([{object_hook, Hook} | Rest], State) ->
80 parse_decoder_options(Rest, State#decoder{object_hook=Hook}).
81
82
83 format_float(F) ->
84 format_float1(lists:reverse(float_to_list(F)), []).
85
86 format_float1([$0, $0, _, $e | Rest], []) ->
87 strip_zeros(Rest, []);
88 format_float1([Sign, $e | Rest], Acc) ->
89 strip_zeros(Rest, [$e, Sign | Acc]);
90 format_float1([C | Rest], Acc) ->
91 format_float1(Rest, [C | Acc]).
92
93 strip_zeros(L=[$0, $. | _], Acc) ->
94 lists:reverse(L, Acc);
95 strip_zeros([$0 | Rest], Acc) ->
96 strip_zeros(Rest, Acc);
97 strip_zeros(L, Acc) ->
98 lists:reverse(L, Acc).
99
100 json_encode(true, _State) ->
101 "true";
102 json_encode(false, _State) ->
103 "false";
104 json_encode(null, _State) ->
105 "null";
106 json_encode(I, _State) when is_integer(I) ->
107 integer_to_list(I);
108 json_encode(F, _State) when is_float(F) ->
109 format_float(F);
110 json_encode(L, State) when is_list(L); is_binary(L); is_atom(L) ->
111 json_encode_string(L, State);
112 json_encode({array, Props}, State) when is_list(Props) ->
113 json_encode_array(Props, State);
114 json_encode({struct, Props}, State) when is_list(Props) ->
115 json_encode_proplist(Props, State);
116 json_encode(Bad, #encoder{handler=null}) ->
117 exit({json_encode, {bad_term, Bad}});
118 json_encode(Bad, State=#encoder{handler=Handler}) ->
119 json_encode(Handler(Bad), State).
120
121 json_encode_array([], _State) ->
122 "[]";
123 json_encode_array(L, State) ->
124 F = fun (O, Acc) ->
125 [$,, json_encode(O, State) | Acc]
126 end,
127 [$, | Acc1] = lists:foldl(F, "[", L),
128 lists:reverse([$\] | Acc1]).
129
130 json_encode_proplist([], _State) ->
131 "{}";
132 json_encode_proplist(Props, State) ->
133 F = fun ({K, V}, Acc) ->
134 KS = case K of
135 K when is_atom(K) ->
136 json_encode_string_utf8(atom_to_list(K), [?Q]);
137 K when is_integer(K) ->
138 json_encode_string(integer_to_list(K), State);
139 K when is_list(K); is_binary(K) ->
140 json_encode_string(K, State)
141 end,
142 VS = json_encode(V, State),
143 [$,, VS, $:, KS | Acc]
144 end,
145 [$, | Acc1] = lists:foldl(F, "{", Props),
146 lists:reverse([$\} | Acc1]).
147
148 json_encode_string(A, _State) when is_atom(A) ->
149 json_encode_string_unicode(xmerl_ucs:from_utf8(atom_to_list(A)), [?Q]);
150 json_encode_string(B, _State) when is_binary(B) ->
151 json_encode_string_unicode(xmerl_ucs:from_utf8(B), [?Q]);
152 json_encode_string(S, #encoder{input_encoding=utf8}) ->
153 json_encode_string_utf8(S, [?Q]);
154 json_encode_string(S, #encoder{input_encoding=unicode}) ->
155 json_encode_string_unicode(S, [?Q]).
156
157 json_encode_string_utf8([], Acc) ->
158 lists:reverse([$\" | Acc]);
159 json_encode_string_utf8(All=[C | Cs], Acc) ->
160 case C of
161 C when C >= 16#7f ->
162 json_encode_string_unicode(xmerl_ucs:from_utf8(All), Acc);
163 _ ->
164 Acc1 = case C of
165 ?Q ->
166 [?Q, $\\ | Acc];
167 $/ ->
168 [$/, $\\ | Acc];
169 $\\ ->
170 [$\\, $\\ | Acc];
171 $\b ->
172 [$b, $\\ | Acc];
173 $\f ->
174 [$f, $\\ | Acc];
175 $\n ->
176 [$n, $\\ | Acc];
177 $\r ->
178 [$r, $\\ | Acc];
179 $\t ->
180 [$t, $\\ | Acc];
181 C when C >= 0, C < $\s ->
182 [unihex(C) | Acc];
183 C when C >= $\s ->
184 [C | Acc];
185 _ ->
186 exit({json_encode, {bad_char, C}})
187 end,
188 json_encode_string_utf8(Cs, Acc1)
189 end.
190
191 json_encode_string_unicode([], Acc) ->
192 lists:reverse([$\" | Acc]);
193 json_encode_string_unicode([C | Cs], Acc) ->
194 Acc1 = case C of
195 ?Q ->
196 [?Q, $\\ | Acc];
197 $/ ->
198 [$/, $\\ | Acc];
199 $\\ ->
200 [$\\, $\\ | Acc];
201 $\b ->
202 [$b, $\\ | Acc];
203 $\f ->
204 [$f, $\\ | Acc];
205 $\n ->
206 [$n, $\\ | Acc];
207 $\r ->
208 [$r, $\\ | Acc];
209 $\t ->
210 [$t, $\\ | Acc];
211 C when C >= 0, C < $\s; C >= 16#7f, C =< 16#10FFFF ->
212 [unihex(C) | Acc];
213 C when C < 16#7f ->
214 [C | Acc];
215 _ ->
216 exit({json_encode, {bad_char, C}})
217 end,
218 json_encode_string_unicode(Cs, Acc1).
219
220 dehex(C) when C >= $0, C =< $9 ->
221 C - $0;
222 dehex(C) when C >= $a, C =< $f ->
223 C - $a + 10;
224 dehex(C) when C >= $A, C =< $F ->
225 C - $A + 10.
226
227 hexdigit(C) when C >= 0, C =< 9 ->
228 C + $0;
229 hexdigit(C) when C =< 15 ->
230 C + $a - 10.
231
232 unihex(C) when C < 16#10000 ->
233 <<D3:4, D2:4, D1:4, D0:4>> = <<C:16>>,
234 Digits = [hexdigit(D) || D <- [D3, D2, D1, D0]],
235 [$\\, $u | Digits];
236 unihex(C) when C =< 16#10FFFF ->
237 N = C - 16#10000,
238 S1 = 16#d800 bor ((N bsr 10) band 16#3ff),
239 S2 = 16#dc00 bor (N band 16#3ff),
240 [unihex(S1), unihex(S2)].
241
242 json_decode(B, S) when is_binary(B) ->
243 json_decode([B], S);
244 json_decode(L, S) ->
245 {Res, L1, S1} = decode1(L, S),
246 {eof, [], _} = tokenize(L1, S1#decoder{state=trim}),
247 Res.
248
249 decode1(L, S=#decoder{state=null}) ->
250 case tokenize(L, S#decoder{state=any}) of
251 {{const, C}, L1, S1} ->
252 {C, L1, S1};
253 {start_array, L1, S1} ->
254 decode_array(L1, S1#decoder{state=any}, []);
255 {start_object, L1, S1} ->
256 decode_object(L1, S1#decoder{state=key}, [])
257 end.
258
259 make_object(V, #decoder{object_hook=null}) ->
260 V;
261 make_object(V, #decoder{object_hook=Hook}) ->
262 Hook(V).
263
264 decode_object(L, S=#decoder{state=key}, Acc) ->
265 case tokenize(L, S) of
266 {end_object, Rest, S1} ->
267 V = make_object({struct, lists:reverse(Acc)}, S1),
268 {V, Rest, S1#decoder{state=null}};
269 {{const, K}, Rest, S1} when is_list(K) ->
270 {colon, L2, S2} = tokenize(Rest, S1),
271 {V, L3, S3} = decode1(L2, S2#decoder{state=null}),
272 decode_object(L3, S3#decoder{state=comma}, [{K, V} | Acc])
273 end;
274 decode_object(L, S=#decoder{state=comma}, Acc) ->
275 case tokenize(L, S) of
276 {end_object, Rest, S1} ->
277 V = make_object({struct, lists:reverse(Acc)}, S1),
278 {V, Rest, S1#decoder{state=null}};
279 {comma, Rest, S1} ->
280 decode_object(Rest, S1#decoder{state=key}, Acc)
281 end.
282
283 decode_array(L, S=#decoder{state=any}, Acc) ->
284 case tokenize(L, S) of
285 {end_array, Rest, S1} ->
286 {{array, lists:reverse(Acc)}, Rest, S1#decoder{state=null}};
287 {start_array, Rest, S1} ->
288 {Array, Rest1, S2} = decode_array(Rest, S1#decoder{state=any}, []),
289 decode_array(Rest1, S2#decoder{state=comma}, [Array | Acc]);
290 {start_object, Rest, S1} ->
291 {Array, Rest1, S2} = decode_object(Rest, S1#decoder{state=key}, []),
292 decode_array(Rest1, S2#decoder{state=comma}, [Array | Acc]);
293 {{const, Const}, Rest, S1} ->
294 decode_array(Rest, S1#decoder{state=comma}, [Const | Acc])
295 end;
296 decode_array(L, S=#decoder{state=comma}, Acc) ->
297 case tokenize(L, S) of
298 {end_array, Rest, S1} ->
299 {{array, lists:reverse(Acc)}, Rest, S1#decoder{state=null}};
300 {comma, Rest, S1} ->
301 decode_array(Rest, S1#decoder{state=any}, Acc)
302 end.
303
304 tokenize_string(IoList=[C | _], S=#decoder{input_encoding=utf8}, Acc)
305 when is_list(C); is_binary(C); C >= 16#7f ->
306 List = xmerl_ucs:from_utf8(iolist_to_binary(IoList)),
307 tokenize_string(List, S#decoder{input_encoding=unicode}, Acc);
308 tokenize_string("\"" ++ Rest, S, Acc) ->
309 {lists:reverse(Acc), Rest, ?INC_COL(S)};
310 tokenize_string("\\\"" ++ Rest, S, Acc) ->
311 tokenize_string(Rest, ?ADV_COL(S, 2), [$\" | Acc]);
312 tokenize_string("\\\\" ++ Rest, S, Acc) ->
313 tokenize_string(Rest, ?ADV_COL(S, 2), [$\\ | Acc]);
314 tokenize_string("\\/" ++ Rest, S, Acc) ->
315 tokenize_string(Rest, ?ADV_COL(S, 2), [$/ | Acc]);
316 tokenize_string("\\b" ++ Rest, S, Acc) ->
317 tokenize_string(Rest, ?ADV_COL(S, 2), [$\b | Acc]);
318 tokenize_string("\\f" ++ Rest, S, Acc) ->
319 tokenize_string(Rest, ?ADV_COL(S, 2), [$\\ | Acc]);
320 tokenize_string("\\n" ++ Rest, S, Acc) ->
321 tokenize_string(Rest, ?ADV_COL(S, 2), [$\n | Acc]);
322 tokenize_string("\\r" ++ Rest, S, Acc) ->
323 tokenize_string(Rest, ?ADV_COL(S, 2), [$\r | Acc]);
324 tokenize_string("\\t" ++ Rest, S, Acc) ->
325 tokenize_string(Rest, ?ADV_COL(S, 2), [$\t | Acc]);
326 tokenize_string([$\\, $u, C3, C2, C1, C0 | Rest], S, Acc) ->
327 % coalesce UTF-16 surrogate pair?
328 C = dehex(C0) bor
329 (dehex(C1) bsl 4) bor
330 (dehex(C2) bsl 8) bor
331 (dehex(C3) bsl 12),
332 tokenize_string(Rest, ?ADV_COL(S, 6), [C | Acc]);
333 tokenize_string([C | Rest], S, Acc) when C >= $\s; C < 16#10FFFF ->
334 tokenize_string(Rest, ?ADV_COL(S, 1), [C | Acc]).
335
336 tokenize_number(IoList=[C | _], Mode, S=#decoder{input_encoding=utf8}, Acc)
337 when is_list(C); is_binary(C); C >= 16#7f ->
338 List = xmerl_ucs:from_utf8(iolist_to_binary(IoList)),
339 tokenize_number(List, Mode, S#decoder{input_encoding=unicode}, Acc);
340 tokenize_number([$- | Rest], sign, S, []) ->
341 tokenize_number(Rest, int, ?INC_COL(S), [$-]);
342 tokenize_number(Rest, sign, S, []) ->
343 tokenize_number(Rest, int, S, []);
344 tokenize_number([$0 | Rest], int, S, Acc) ->
345 tokenize_number(Rest, frac, ?INC_COL(S), [$0 | Acc]);
346 tokenize_number([C | Rest], int, S, Acc) when C >= $1, C =< $9 ->
347 tokenize_number(Rest, int1, ?INC_COL(S), [C | Acc]);
348 tokenize_number([C | Rest], int1, S, Acc) when C >= $0, C =< $9 ->
349 tokenize_number(Rest, int1, ?INC_COL(S), [C | Acc]);
350 tokenize_number(Rest, int1, S, Acc) ->
351 tokenize_number(Rest, frac, S, Acc);
352 tokenize_number([$., C | Rest], frac, S, Acc) when C >= $0, C =< $9 ->
353 tokenize_number(Rest, frac1, ?ADV_COL(S, 2), [C, $. | Acc]);
354 tokenize_number([E | Rest], frac, S, Acc) when E == $e; E == $E ->
355 tokenize_number(Rest, esign, ?INC_COL(S), [$e, $0, $. | Acc]);
356 tokenize_number(Rest, frac, S, Acc) ->
357 {{int, lists:reverse(Acc)}, Rest, S};
358 tokenize_number([C | Rest], frac1, S, Acc) when C >= $0, C =< $9 ->
359 tokenize_number(Rest, frac1, ?INC_COL(S), [C | Acc]);
360 tokenize_number([E | Rest], frac1, S, Acc) when E == $e; E == $E ->
361 tokenize_number(Rest, esign, ?INC_COL(S), [$e | Acc]);
362 tokenize_number(Rest, frac1, S, Acc) ->
363 {{float, lists:reverse(Acc)}, Rest, S};
364 tokenize_number([C | Rest], esign, S, Acc) when C == $-; C == $+ ->
365 tokenize_number(Rest, eint, ?INC_COL(S), [C | Acc]);
366 tokenize_number(Rest, esign, S, Acc) ->
367 tokenize_number(Rest, eint, S, Acc);
368 tokenize_number([C | Rest], eint, S, Acc) when C >= $0, C =< $9 ->
369 tokenize_number(Rest, eint1, ?INC_COL(S), [C | Acc]);
370 tokenize_number([C | Rest], eint1, S, Acc) when C >= $0, C =< $9 ->
371 tokenize_number(Rest, eint1, ?INC_COL(S), [C | Acc]);
372 tokenize_number(Rest, eint1, S, Acc) ->
373 {{float, lists:reverse(Acc)}, Rest, S}.
374
375 tokenize([], S=#decoder{state=trim}) ->
376 {eof, [], S};
377 tokenize([L | Rest], S) when is_list(L) ->
378 tokenize(L ++ Rest, S);
379 tokenize([B | Rest], S) when is_binary(B) ->
380 tokenize(xmerl_ucs:from_utf8(B) ++ Rest, S);
381 tokenize("\r\n" ++ Rest, S) ->
382 tokenize(Rest, ?INC_LINE(S));
383 tokenize("\n" ++ Rest, S) ->
384 tokenize(Rest, ?INC_LINE(S));
385 tokenize([C | Rest], S) when C == $\s; C == $\t ->
386 tokenize(Rest, ?INC_COL(S));
387 tokenize("{" ++ Rest, S) ->
388 {start_object, Rest, ?INC_COL(S)};
389 tokenize("}" ++ Rest, S) ->
390 {end_object, Rest, ?INC_COL(S)};
391 tokenize("[" ++ Rest, S) ->
392 {start_array, Rest, ?INC_COL(S)};
393 tokenize("]" ++ Rest, S) ->
394 {end_array, Rest, ?INC_COL(S)};
395 tokenize("," ++ Rest, S) ->
396 {comma, Rest, ?INC_COL(S)};
397 tokenize(":" ++ Rest, S) ->
398 {colon, Rest, ?INC_COL(S)};
399 tokenize("null" ++ Rest, S) ->
400 {{const, null}, Rest, ?ADV_COL(S, 4)};
401 tokenize("true" ++ Rest, S) ->
402 {{const, true}, Rest, ?ADV_COL(S, 4)};
403 tokenize("false" ++ Rest, S) ->
404 {{const, false}, Rest, ?ADV_COL(S, 5)};
405 tokenize("\"" ++ Rest, S) ->
406 {String, Rest1, S1} = tokenize_string(Rest, ?INC_COL(S), []),
407 {{const, String}, Rest1, S1};
408 tokenize(L=[C | _], S) when C >= $0, C =< $9; C == $- ->
409 case tokenize_number(L, sign, S, []) of
410 {{int, Int}, Rest, S1} ->
411 {{const, list_to_integer(Int)}, Rest, S1};
412 {{float, Float}, Rest, S1} ->
413 {{const, list_to_float(Float)}, Rest, S1}
414 end.
415
416 %% testing constructs borrowed from the Yaws JSON implementation.
417
418 %% Create an object from a list of Key/Value pairs.
419
420 obj_new() ->
421 {struct, []}.
422
423 is_obj({struct, Props}) ->
424 F = fun ({K, _}) when is_list(K) ->
425 true;
426 (_) ->
427 false
428 end,
429 lists:all(F, Props).
430
431 obj_from_list(Props) ->
432 Obj = {struct, Props},
433 case is_obj(Obj) of
434 true -> Obj;
435 false -> exit(json_bad_object)
436 end.
437
438 %% Test for equivalence of Erlang terms.
439 %% Due to arbitrary order of construction, equivalent objects might
440 %% compare unequal as erlang terms, so we need to carefully recurse
441 %% through aggregates (tuples and objects).
442
443 equiv({struct, Props1}, {struct, Props2}) ->
444 equiv_object(Props1, Props2);
445 equiv({array, L1}, {array, L2}) ->
446 equiv_list(L1, L2);
447 equiv(N1, N2) when is_number(N1), is_number(N2) -> N1 == N2;
448 equiv(S1, S2) when is_list(S1), is_list(S2) -> S1 == S2;
449 equiv(true, true) -> true;
450 equiv(false, false) -> true;
451 equiv(null, null) -> true.
452
453 %% Object representation and traversal order is unknown.
454 %% Use the sledgehammer and sort property lists.
455
456 equiv_object(Props1, Props2) ->
457 L1 = lists:keysort(1, Props1),
458 L2 = lists:keysort(1, Props2),
459 Pairs = lists:zip(L1, L2),
460 true = lists:all(fun({{K1, V1}, {K2, V2}}) ->
461 equiv(K1, K2) and equiv(V1, V2)
462 end, Pairs).
463
464 %% Recursively compare tuple elements for equivalence.
465
466 equiv_list([], []) ->
467 true;
468 equiv_list([V1 | L1], [V2 | L2]) ->
469 case equiv(V1, V2) of
470 true ->
471 equiv_list(L1, L2);
472 false ->
473 false
474 end.
475
476 test_all() ->
477 test_one(e2j_test_vec(utf8), 1).
478
479 test_one([], _N) ->
480 %% io:format("~p tests passed~n", [N-1]),
481 ok;
482 test_one([{E, J} | Rest], N) ->
483 %% io:format("[~p] ~p ~p~n", [N, E, J]),
484 true = equiv(E, decode(J)),
485 true = equiv(E, decode(encode(E))),
486 test_one(Rest, 1+N).
487
488 e2j_test_vec(unicode) ->
489 [
490 {"foo" ++ [500] ++ "bar", [$", $f, $o, $o, 500, $b, $a, $r, $"]}
491 ];
492 e2j_test_vec(utf8) ->
493 [
494 {1, "1"},
495 {3.1416, "3.14160"}, % text representation may truncate, trail zeroes
496 {-1, "-1"},
497 {-3.1416, "-3.14160"},
498 {12.0e10, "1.20000e+11"},
499 {1.234E+10, "1.23400e+10"},
500 {-1.234E-10, "-1.23400e-10"},
501 {10.0, "1.0e+01"},
502 {123.456, "1.23456E+2"},
503 {10.0, "1e1"},
504 {"foo", "\"foo\""},
505 {"foo" ++ [5] ++ "bar", "\"foo\\u0005bar\""},
506 {"", "\"\""},
507 {[], "\"\""},
508 {"\n\n\n", "\"\\n\\n\\n\""},
509 {obj_new(), "{}"},
510 {obj_from_list([{"foo", "bar"}]), "{\"foo\":\"bar\"}"},
511 {obj_from_list([{"foo", "bar"}, {"baz", 123}]),
512 "{\"foo\":\"bar\",\"baz\":123}"},
513 {{array, []}, "[]"},
514 {{array, [{array, []}]}, "[[]]"},
515 {{array, [1, "foo"]}, "[1,\"foo\"]"},
516
517 % json array in a json object
518 {obj_from_list([{"foo", {array, [123]}}]),
519 "{\"foo\":[123]}"},
520
521 % json object in a json object
522 {obj_from_list([{"foo", obj_from_list([{"bar", true}])}]),
523 "{\"foo\":{\"bar\":true}}"},
524
525 % fold evaluation order
526 {obj_from_list([{"foo", {array, []}},
527 {"bar", obj_from_list([{"baz", true}])},
528 {"alice", "bob"}]),
529 "{\"foo\":[],\"bar\":{\"baz\":true},\"alice\":\"bob\"}"},
530
531 % json object in a json array
532 {{array, [-123, "foo", obj_from_list([{"bar", {array, []}}]), null]},
533 "[-123,\"foo\",{\"bar\":[]},null]"}
534 ].
Something went wrong with that request. Please try again.