allow a single trailing comma in objects or arrays
This commit is contained in:
parent
c25bb49902
commit
6b43609730
4 changed files with 56 additions and 0 deletions
|
@ -133,6 +133,10 @@ number of ways. see the section on `strict` in [options](#option) below though
|
||||||
json has no official comments but this parser allows c/c++ style comments.
|
json has no official comments but this parser allows c/c++ style comments.
|
||||||
anywhere whitespace is allowed you can insert comments (both `// ...` and `/* ... */`)
|
anywhere whitespace is allowed you can insert comments (both `// ...` and `/* ... */`)
|
||||||
|
|
||||||
|
some particularly irresponsible json emitters leave trailing commas at the end of
|
||||||
|
objects or arrays. **jsx** allows a single trailing comma in input. multiple commas
|
||||||
|
in any posistion or a preceding comma are still errors
|
||||||
|
|
||||||
all **jsx** decoder input should be `utf8` encoded binaries. sometimes you get binaries
|
all **jsx** decoder input should be `utf8` encoded binaries. sometimes you get binaries
|
||||||
that are almost but not quite valid utf8 whether due to improper escaping or poor
|
that are almost but not quite valid utf8 whether due to improper escaping or poor
|
||||||
encoding. **jsx** replaces invalid codepoints and poorly formed sequences with the
|
encoding. **jsx** replaces invalid codepoints and poorly formed sequences with the
|
||||||
|
@ -337,6 +341,7 @@ option() = escaped_forward_slashes
|
||||||
| stream
|
| stream
|
||||||
|
|
||||||
strict_option() = comments
|
strict_option() = comments
|
||||||
|
| trailing_commas
|
||||||
| utf8
|
| utf8
|
||||||
| single_quotes
|
| single_quotes
|
||||||
| escapes
|
| escapes
|
||||||
|
@ -390,6 +395,10 @@ additional options beyond these. see
|
||||||
|
|
||||||
comments are disabled and result in a `badarg` error
|
comments are disabled and result in a `badarg` error
|
||||||
|
|
||||||
|
* `trailing_commas`
|
||||||
|
|
||||||
|
trailing commas in an object or list result in `badarg` errors
|
||||||
|
|
||||||
* `utf8`
|
* `utf8`
|
||||||
|
|
||||||
invalid codepoints and malformed unicode result in `badarg` errors
|
invalid codepoints and malformed unicode result in `badarg` errors
|
||||||
|
|
|
@ -65,6 +65,7 @@ parse_config([dirty_strings|Rest], Config) ->
|
||||||
parse_config(Rest, Config#config{dirty_strings=true});
|
parse_config(Rest, Config#config{dirty_strings=true});
|
||||||
parse_config([strict|Rest], Config) ->
|
parse_config([strict|Rest], Config) ->
|
||||||
parse_config(Rest, Config#config{strict_comments=true,
|
parse_config(Rest, Config#config{strict_comments=true,
|
||||||
|
strict_commas=true,
|
||||||
strict_utf8=true,
|
strict_utf8=true,
|
||||||
strict_single_quotes=true,
|
strict_single_quotes=true,
|
||||||
strict_escapes=true
|
strict_escapes=true
|
||||||
|
@ -89,6 +90,8 @@ parse_config(_Options, _Config) -> erlang:error(badarg).
|
||||||
parse_strict([], Rest, Config) -> parse_config(Rest, Config);
|
parse_strict([], Rest, Config) -> parse_config(Rest, Config);
|
||||||
parse_strict([comments|Strict], Rest, Config) ->
|
parse_strict([comments|Strict], Rest, Config) ->
|
||||||
parse_strict(Strict, Rest, Config#config{strict_comments=true});
|
parse_strict(Strict, Rest, Config#config{strict_comments=true});
|
||||||
|
parse_strict([trailing_commas|Strict], Rest, Config) ->
|
||||||
|
parse_strict(Strict, Rest, Config#config{strict_commas=true});
|
||||||
parse_strict([utf8|Strict], Rest, Config) ->
|
parse_strict([utf8|Strict], Rest, Config) ->
|
||||||
parse_strict(Strict, Rest, Config#config{strict_utf8=true});
|
parse_strict(Strict, Rest, Config#config{strict_utf8=true});
|
||||||
parse_strict([single_quotes|Strict], Rest, Config) ->
|
parse_strict([single_quotes|Strict], Rest, Config) ->
|
||||||
|
@ -182,6 +185,7 @@ config_test_() ->
|
||||||
unescaped_jsonp = true,
|
unescaped_jsonp = true,
|
||||||
dirty_strings = true,
|
dirty_strings = true,
|
||||||
strict_comments = true,
|
strict_comments = true,
|
||||||
|
strict_commas = true,
|
||||||
strict_utf8 = true,
|
strict_utf8 = true,
|
||||||
strict_single_quotes = true,
|
strict_single_quotes = true,
|
||||||
strict_escapes = true,
|
strict_escapes = true,
|
||||||
|
@ -199,6 +203,7 @@ config_test_() ->
|
||||||
{"strict flag",
|
{"strict flag",
|
||||||
?_assertEqual(
|
?_assertEqual(
|
||||||
#config{strict_comments = true,
|
#config{strict_comments = true,
|
||||||
|
strict_commas = true,
|
||||||
strict_utf8 = true,
|
strict_utf8 = true,
|
||||||
strict_single_quotes = true,
|
strict_single_quotes = true,
|
||||||
strict_escapes = true
|
strict_escapes = true
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
unescaped_jsonp = false :: boolean(),
|
unescaped_jsonp = false :: boolean(),
|
||||||
dirty_strings = false :: boolean(),
|
dirty_strings = false :: boolean(),
|
||||||
strict_comments = false :: boolean(),
|
strict_comments = false :: boolean(),
|
||||||
|
strict_commas = false :: boolean(),
|
||||||
strict_utf8 = false :: boolean(),
|
strict_utf8 = false :: boolean(),
|
||||||
strict_single_quotes = false :: boolean(),
|
strict_single_quotes = false :: boolean(),
|
||||||
strict_escapes = false :: boolean(),
|
strict_escapes = false :: boolean(),
|
||||||
|
|
|
@ -211,6 +211,8 @@ value(<<?start_array, Rest/binary>>, Handler, Stack, Config) ->
|
||||||
array(Rest, handle_event(start_array, Handler, Config), [array|Stack], Config);
|
array(Rest, handle_event(start_array, Handler, Config), [array|Stack], Config);
|
||||||
value(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) ->
|
value(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) ->
|
||||||
value(Rest, Handler, Stack, Config);
|
value(Rest, Handler, Stack, Config);
|
||||||
|
value(<<?end_array, _/binary>> = Rest, Handler, Stack, Config=#config{strict_commas=false}) ->
|
||||||
|
maybe_done(Rest, Handler, Stack, Config);
|
||||||
value(<<?solidus, Rest/binary>>, Handler, Stack, Config=#config{strict_comments=true}) ->
|
value(<<?solidus, Rest/binary>>, Handler, Stack, Config=#config{strict_comments=true}) ->
|
||||||
?error(value, <<?solidus, Rest/binary>>, Handler, Stack, Config);
|
?error(value, <<?solidus, Rest/binary>>, Handler, Stack, Config);
|
||||||
value(<<?solidus, ?solidus, Rest/binary>>, Handler, Stack, Config) ->
|
value(<<?solidus, ?solidus, Rest/binary>>, Handler, Stack, Config) ->
|
||||||
|
@ -289,6 +291,8 @@ key(<<?singlequote, Rest/binary>>, Handler, Stack, Config=#config{strict_single_
|
||||||
string(Rest, Handler, new_seq(), [singlequote|Stack], Config);
|
string(Rest, Handler, new_seq(), [singlequote|Stack], Config);
|
||||||
key(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) ->
|
key(<<S, Rest/binary>>, Handler, Stack, Config) when ?is_whitespace(S) ->
|
||||||
key(Rest, Handler, Stack, Config);
|
key(Rest, Handler, Stack, Config);
|
||||||
|
key(<<?end_object, Rest/binary>>, Handler, [key|Stack], Config=#config{strict_commas=false}) ->
|
||||||
|
maybe_done(<<?end_object, Rest/binary>>, Handler, [object|Stack], Config);
|
||||||
key(<<?solidus, Rest/binary>>, Handler, Stack, Config=#config{strict_comments=true}) ->
|
key(<<?solidus, Rest/binary>>, Handler, Stack, Config=#config{strict_comments=true}) ->
|
||||||
?error(key, <<?solidus, Rest/binary>>, Handler, Stack, Config);
|
?error(key, <<?solidus, Rest/binary>>, Handler, Stack, Config);
|
||||||
key(<<?solidus, ?solidus, Rest/binary>>, Handler, Stack, Config) ->
|
key(<<?solidus, ?solidus, Rest/binary>>, Handler, Stack, Config) ->
|
||||||
|
@ -1627,6 +1631,43 @@ bom_test_() ->
|
||||||
].
|
].
|
||||||
|
|
||||||
|
|
||||||
|
trailing_comma_test_() ->
|
||||||
|
[
|
||||||
|
{"trailing comma in object", ?_assertEqual(
|
||||||
|
[start_object, {key, <<"key">>}, {literal, true}, end_object, end_json],
|
||||||
|
decode(<<"{\"key\": true,}">>, [])
|
||||||
|
)},
|
||||||
|
{"strict trailing comma in object", ?_assertError(
|
||||||
|
badarg,
|
||||||
|
decode(<<"{\"key\": true,}">>, [{strict, [trailing_commas]}])
|
||||||
|
)},
|
||||||
|
{"two trailing commas in object", ?_assertError(
|
||||||
|
badarg,
|
||||||
|
decode(<<"{\"key\": true,,}">>, [])
|
||||||
|
)},
|
||||||
|
{"comma in empty object", ?_assertError(
|
||||||
|
badarg,
|
||||||
|
decode(<<"{,}">>, [])
|
||||||
|
)},
|
||||||
|
{"trailing comma in list", ?_assertEqual(
|
||||||
|
[start_array, {literal, true}, end_array, end_json],
|
||||||
|
decode(<<"[true,]">>, [])
|
||||||
|
)},
|
||||||
|
{"strict trailing comma in list", ?_assertError(
|
||||||
|
badarg,
|
||||||
|
decode(<<"[true,]">>, [{strict, [trailing_commas]}])
|
||||||
|
)},
|
||||||
|
{"two trailing commas in list", ?_assertError(
|
||||||
|
badarg,
|
||||||
|
decode(<<"[true,,]">>, [])
|
||||||
|
)},
|
||||||
|
{"comma in empty list", ?_assertError(
|
||||||
|
badarg,
|
||||||
|
decode(<<"[,]">>, [])
|
||||||
|
)}
|
||||||
|
].
|
||||||
|
|
||||||
|
|
||||||
incomplete_test_() ->
|
incomplete_test_() ->
|
||||||
[
|
[
|
||||||
{"stream false", ?_assertError(
|
{"stream false", ?_assertError(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue