use end_json
to end streaming when in streaming mode in addition
to `end_stream`
This commit is contained in:
parent
b14714aef9
commit
c25bb49902
5 changed files with 38 additions and 7 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
v2.1
|
||||||
|
|
||||||
|
* force the end of streams with `end_json` in addition to `end_stream`
|
||||||
|
|
||||||
v2.0.4
|
v2.0.4
|
||||||
|
|
||||||
* more typespec adjustments
|
* more typespec adjustments
|
||||||
|
|
|
@ -264,16 +264,16 @@ memory
|
||||||
however, it is important to recognize that **jsx** is conservative by default. **jsx** will
|
however, it is important to recognize that **jsx** is conservative by default. **jsx** will
|
||||||
not consider the parsing complete even when input is exhausted and the json text is
|
not consider the parsing complete even when input is exhausted and the json text is
|
||||||
unambiguously incomplete. to end parsing call the `incomplete` function with the
|
unambiguously incomplete. to end parsing call the `incomplete` function with the
|
||||||
argument `end_stream` like:
|
argument `end_stream` (or `end_json`) like:
|
||||||
|
|
||||||
```erlang
|
```erlang
|
||||||
1> {incomplete, F} = jsx:decode(<<"[">>, [stream]).
|
1> {incomplete, F} = jsx:decode(<<"[">>, [stream]).
|
||||||
{incomplete,#Fun<jsx_decoder.1.122947756>}
|
{incomplete,#Fun<jsx_decoder.1.122947756>}
|
||||||
2> F(end_stream).
|
2> F(end_stream). % can also be `F(end_json)`
|
||||||
** exception error: bad argument
|
** exception error: bad argument
|
||||||
3> {incomplete, G} = F(<<"]">>).
|
3> {incomplete, G} = F(<<"]">>).
|
||||||
{incomplete,#Fun<jsx_decoder.1.122947756>}
|
{incomplete,#Fun<jsx_decoder.1.122947756>}
|
||||||
4> G(end_stream).
|
4> G(end_stream). % can also be `G(end_json)`
|
||||||
[]
|
[]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
31
src/jsx.erl
31
src/jsx.erl
|
@ -107,14 +107,14 @@ is_term(Source) -> is_term(Source, []).
|
||||||
is_term(Source, Config) -> jsx_verify:is_term(Source, Config).
|
is_term(Source, Config) -> jsx_verify:is_term(Source, Config).
|
||||||
|
|
||||||
|
|
||||||
-type decoder() :: fun((json_text() | end_stream) -> any()).
|
-type decoder() :: fun((json_text() | end_stream | end_json) -> any()).
|
||||||
|
|
||||||
-spec decoder(Handler::module(), State::any(), Config::list()) -> decoder().
|
-spec decoder(Handler::module(), State::any(), Config::list()) -> decoder().
|
||||||
|
|
||||||
decoder(Handler, State, Config) -> jsx_decoder:decoder(Handler, State, Config).
|
decoder(Handler, State, Config) -> jsx_decoder:decoder(Handler, State, Config).
|
||||||
|
|
||||||
|
|
||||||
-type encoder() :: fun((json_term() | end_stream) -> any()).
|
-type encoder() :: fun((json_term() | end_stream | end_json) -> any()).
|
||||||
|
|
||||||
-spec encoder(Handler::module(), State::any(), Config::list()) -> encoder().
|
-spec encoder(Handler::module(), State::any(), Config::list()) -> encoder().
|
||||||
|
|
||||||
|
@ -464,5 +464,32 @@ encode_test_() ->
|
||||||
} || {Title, _, Term, Events} <- Data
|
} || {Title, _, Term, Events} <- Data
|
||||||
].
|
].
|
||||||
|
|
||||||
|
end_stream_test_() ->
|
||||||
|
Tokens = [start_object, end_object, end_json],
|
||||||
|
[
|
||||||
|
{"encoder end_stream", ?_assertEqual(
|
||||||
|
Tokens,
|
||||||
|
begin
|
||||||
|
{incomplete, F} = (jsx:parser(jsx, [], [stream]))([start_object, end_object]),
|
||||||
|
F(end_stream)
|
||||||
|
end
|
||||||
|
)},
|
||||||
|
{"encoder end_json", ?_assertEqual(
|
||||||
|
Tokens,
|
||||||
|
begin
|
||||||
|
{incomplete, F} = (jsx:parser(jsx, [], [stream]))([start_object, end_object]),
|
||||||
|
F(end_json)
|
||||||
|
end
|
||||||
|
)},
|
||||||
|
{"decoder end_stream", ?_assertEqual(
|
||||||
|
Tokens,
|
||||||
|
begin {incomplete, F} = (jsx:decoder(jsx, [], [stream]))(<<"{}">>), F(end_stream) end
|
||||||
|
)},
|
||||||
|
{"decoder end_json", ?_assertEqual(
|
||||||
|
Tokens,
|
||||||
|
begin {incomplete, F} = (jsx:decoder(jsx, [], [stream]))(<<"{}">>), F(end_json) end
|
||||||
|
)}
|
||||||
|
].
|
||||||
|
|
||||||
|
|
||||||
-endif.
|
-endif.
|
||||||
|
|
|
@ -150,7 +150,7 @@ incomplete(State, Rest, Handler, Acc, Stack, Config = #config{stream=false}) ->
|
||||||
incomplete(State, Rest, Handler, Acc, Stack, Config = #config{incomplete_handler=false}) ->
|
incomplete(State, Rest, Handler, Acc, Stack, Config = #config{incomplete_handler=false}) ->
|
||||||
{incomplete, fun(Stream) when is_binary(Stream) ->
|
{incomplete, fun(Stream) when is_binary(Stream) ->
|
||||||
resume(<<Rest/binary, Stream/binary>>, State, Handler, Acc, Stack, Config);
|
resume(<<Rest/binary, Stream/binary>>, State, Handler, Acc, Stack, Config);
|
||||||
(end_stream) ->
|
(End) when End == end_stream; End == end_json ->
|
||||||
case resume(<<Rest/binary, ?space/utf8>>, State, Handler, Acc, Stack, Config#config{stream=false}) of
|
case resume(<<Rest/binary, ?space/utf8>>, State, Handler, Acc, Stack, Config#config{stream=false}) of
|
||||||
{incomplete, _} -> ?error(State, Rest, Handler, Acc, Stack, Config);
|
{incomplete, _} -> ?error(State, Rest, Handler, Acc, Stack, Config);
|
||||||
Else -> Else
|
Else -> Else
|
||||||
|
|
|
@ -71,7 +71,7 @@ resume(Rest, State, Handler, Stack, Config) ->
|
||||||
incomplete(State, Handler, Stack, Config=#config{stream=false}) ->
|
incomplete(State, Handler, Stack, Config=#config{stream=false}) ->
|
||||||
?error(State, [], Handler, Stack, Config);
|
?error(State, [], Handler, Stack, Config);
|
||||||
incomplete(State, Handler, Stack, Config=#config{incomplete_handler=false}) ->
|
incomplete(State, Handler, Stack, Config=#config{incomplete_handler=false}) ->
|
||||||
{incomplete, fun(end_stream) ->
|
{incomplete, fun(End) when End == end_stream; End == end_json ->
|
||||||
case resume([end_json], State, Handler, Stack, Config) of
|
case resume([end_json], State, Handler, Stack, Config) of
|
||||||
{incomplete, _} -> ?error(State, [], Handler, Stack, Config);
|
{incomplete, _} -> ?error(State, [], Handler, Stack, Config);
|
||||||
Else -> Else
|
Else -> Else
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue