Merge branch 'develop' into vtwopointoh
This commit is contained in:
commit
3bb65e9bab
12 changed files with 104 additions and 45 deletions
13
CHANGES.md
13
CHANGES.md
|
@ -1,3 +1,14 @@
|
||||||
|
v1.4.5
|
||||||
|
|
||||||
|
* various fixes to typespecs uncovered by dialyzer
|
||||||
|
* allow integer keys during encoding
|
||||||
|
* convert atoms (other than `true`, `false` and `null`) to strings during encoding
|
||||||
|
|
||||||
|
v1.4.4
|
||||||
|
|
||||||
|
* typespec for `json_term/0` fixed
|
||||||
|
* incorrect boolean shortcircuiting fixed in multibyte escape processing
|
||||||
|
|
||||||
v1.4.3
|
v1.4.3
|
||||||
|
|
||||||
* add empty rebar.config for mix build tool
|
* add empty rebar.config for mix build tool
|
||||||
|
@ -72,4 +83,4 @@ v1.0.2
|
||||||
|
|
||||||
v1.0.1
|
v1.0.1
|
||||||
|
|
||||||
* rebar fix
|
* rebar fix
|
||||||
|
|
22
README.md
22
README.md
|
@ -144,8 +144,8 @@ ignores bad escape sequences
|
||||||
|
|
||||||
**json** | **erlang**
|
**json** | **erlang**
|
||||||
--------------------------------|--------------------------------
|
--------------------------------|--------------------------------
|
||||||
`number` | `integer()` if possible, `float()` otherwise
|
`number` | `integer()` and `float()`
|
||||||
`string` | `binary()`
|
`string` | `binary()` and `atom()`
|
||||||
`true`, `false` and `null` | `true`, `false` and `null`
|
`true`, `false` and `null` | `true`, `false` and `null`
|
||||||
`array` | `[]` and `[JSON]`
|
`array` | `[]` and `[JSON]`
|
||||||
`object` | `[{}]` and `[{binary() OR atom(), JSON}]`
|
`object` | `[{}]` and `[{binary() OR atom(), JSON}]`
|
||||||
|
@ -171,9 +171,10 @@ ignores bad escape sequences
|
||||||
|
|
||||||
* strings
|
* strings
|
||||||
|
|
||||||
json strings must be unicode. in practice, because **jsx** only accepts
|
json strings must be unicode encoded binaries or erlang atoms. in practice,
|
||||||
`utf8` all strings must be `utf8`. in addition to being unicode json strings
|
because **jsx** only accepts `utf8` binaries all binary strings must be `utf8`.
|
||||||
restrict a number of codepoints and define a number of escape sequences
|
in addition to being unicode json strings restrict a number of codepoints and
|
||||||
|
define a number of escape sequences
|
||||||
|
|
||||||
json string escapes of the form `\uXXXX` will be converted to their
|
json string escapes of the form `\uXXXX` will be converted to their
|
||||||
equivalent codepoints during parsing. this means control characters and
|
equivalent codepoints during parsing. this means control characters and
|
||||||
|
@ -208,9 +209,9 @@ ignores bad escape sequences
|
||||||
special representation `[{}]` to differentiate it from the empty list.
|
special representation `[{}]` to differentiate it from the empty list.
|
||||||
ambiguities like `[true, false]` prevent the use of the shorthand form of
|
ambiguities like `[true, false]` prevent the use of the shorthand form of
|
||||||
property lists using atoms as properties so all properties must be tuples.
|
property lists using atoms as properties so all properties must be tuples.
|
||||||
all keys must be encoded as in `string` or as atoms (which will be escaped
|
all keys must be encoded as in `string` or as atoms or integers (which will
|
||||||
and converted to binaries for presentation to handlers). values should be
|
be escaped and converted to binaries for presentation to handlers). values
|
||||||
valid json values
|
should be valid json values
|
||||||
|
|
||||||
|
|
||||||
### incomplete input ###
|
### incomplete input ###
|
||||||
|
@ -254,6 +255,7 @@ json_term() = [json_term()]
|
||||||
| integer()
|
| integer()
|
||||||
| float()
|
| float()
|
||||||
| binary()
|
| binary()
|
||||||
|
| atom()
|
||||||
```
|
```
|
||||||
|
|
||||||
the erlang representation of json. binaries should be `utf8` encoded, or close
|
the erlang representation of json. binaries should be `utf8` encoded, or close
|
||||||
|
@ -631,7 +633,7 @@ following events must be handled:
|
||||||
|
|
||||||
## acknowledgements ##
|
## acknowledgements ##
|
||||||
|
|
||||||
**jsx** wouldn't be what it is without the contributions of [paul davis](https://github.com/davisp), [lloyd hilaiel](https://github.com/lloyd), [john engelhart](https://github.com/johnezang), [bob ippolito](https://github.com/etrepum), [fernando benavides](https://github.com/elbrujohalcon), [alex kropivny](https://github.com/amtal), [steve strong](https://github.com/srstrong), [michael truog](https://github.com/okeuday), [dmitry kolesnikov](https://github.com/fogfish) and [emptytea](https://github.com/emptytea)
|
jsx wouldn't be what it is without the contributions of [paul davis](https://github.com/davisp), [lloyd hilaiel](https://github.com/lloyd), [john engelhart](https://github.com/johnezang), [bob ippolito](https://github.com/etrepum), [fernando benavides](https://github.com/elbrujohalcon), [alex kropivny](https://github.com/amtal), [steve strong](https://github.com/srstrong), [michael truog](https://github.com/okeuday), [devin torres](https://github.com/devinus), [dmitry kolesnikov](https://github.com/fogfish), [emptytea](https://github.com/emptytea), [john daily](https://github.com/macintux), [ola bäckström](https://github.com/olabackstrom), [joseph crowe](https://github.com/JosephCrowe), [patrick gombert](https://github.com/patrickgombert), [eskuat](https://github.com/eskuat) and [max lapshin](https://github.com/maxlapshin)
|
||||||
|
|
||||||
[json]: http://json.org
|
[json]: http://json.org
|
||||||
[yajl]: http://lloyd.github.com/yajl
|
[yajl]: http://lloyd.github.com/yajl
|
||||||
|
@ -639,4 +641,4 @@ following events must be handled:
|
||||||
[rebar]: https://github.com/rebar/rebar
|
[rebar]: https://github.com/rebar/rebar
|
||||||
[meck]: https://github.com/eproxus/meck
|
[meck]: https://github.com/eproxus/meck
|
||||||
[rfc4627]: http://tools.ietf.org/html/rfc4627
|
[rfc4627]: http://tools.ietf.org/html/rfc4627
|
||||||
[travis]: https://travis-ci.org/
|
[travis]: https://travis-ci.org/
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{application, jsx,
|
{application, jsx,
|
||||||
[
|
[
|
||||||
{description, "a streaming, evented json parsing toolkit"},
|
{description, "a streaming, evented json parsing toolkit"},
|
||||||
{vsn, "1.4.3"},
|
{vsn, "1.4.4"},
|
||||||
{modules, [
|
{modules, [
|
||||||
jsx,
|
jsx,
|
||||||
jsx_encoder,
|
jsx_encoder,
|
||||||
|
|
|
@ -48,11 +48,11 @@
|
||||||
| null
|
| null
|
||||||
| integer()
|
| integer()
|
||||||
| float()
|
| float()
|
||||||
| binary().
|
| binary()
|
||||||
|
| atom().
|
||||||
|
|
||||||
-type json_text() :: binary().
|
-type json_text() :: binary().
|
||||||
|
|
||||||
|
|
||||||
-spec encode(Source::json_term()) -> json_text() | {incomplete, encoder()}.
|
-spec encode(Source::json_term()) -> json_text() | {incomplete, encoder()}.
|
||||||
-spec encode(Source::json_term(), Config::jsx_to_json:config()) -> json_text() | {incomplete, encoder()}.
|
-spec encode(Source::json_term(), Config::jsx_to_json:config()) -> json_text() | {incomplete, encoder()}.
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,22 @@
|
||||||
|
|
||||||
-include("jsx_config.hrl").
|
-include("jsx_config.hrl").
|
||||||
|
|
||||||
|
-type handler_type(Handler) ::
|
||||||
|
fun((jsx:json_text() | end_stream |
|
||||||
|
jsx:json_term(),
|
||||||
|
{decoder, any(), module(), null | list(), list()} |
|
||||||
|
{parser, any(), module(), list()} |
|
||||||
|
{encoder, any(), module()},
|
||||||
|
list({pre_encode, fun((any()) -> any())} |
|
||||||
|
{error_handler, Handler} |
|
||||||
|
{incomplete_handler, Handler} |
|
||||||
|
atom())) -> any()).
|
||||||
|
-type handler() :: handler_type(handler()).
|
||||||
|
-export_type([handler/0]).
|
||||||
|
|
||||||
%% parsing of jsx config
|
%% parsing of jsx config
|
||||||
|
-spec parse_config(Config::proplists:proplist()) -> jsx:config().
|
||||||
|
|
||||||
parse_config(Config) -> parse_config(Config, #config{}).
|
parse_config(Config) -> parse_config(Config, #config{}).
|
||||||
|
|
||||||
parse_config([], Config) -> Config;
|
parse_config([], Config) -> Config;
|
||||||
|
@ -83,6 +97,8 @@ parse_strict(_Strict, _Rest, _Config) ->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-spec config_to_list(Config::jsx:config()) -> proplists:proplist().
|
||||||
|
|
||||||
config_to_list(Config) ->
|
config_to_list(Config) ->
|
||||||
reduce_config(lists:map(
|
reduce_config(lists:map(
|
||||||
fun ({error_handler, F}) -> {error_handler, F};
|
fun ({error_handler, F}) -> {error_handler, F};
|
||||||
|
@ -116,6 +132,8 @@ reduce_config([Else|Input], Output, Strict) ->
|
||||||
reduce_config(Input, [Else] ++ Output, Strict).
|
reduce_config(Input, [Else] ++ Output, Strict).
|
||||||
|
|
||||||
|
|
||||||
|
-spec valid_flags() -> [atom()].
|
||||||
|
|
||||||
valid_flags() ->
|
valid_flags() ->
|
||||||
[
|
[
|
||||||
escaped_forward_slashes,
|
escaped_forward_slashes,
|
||||||
|
@ -129,6 +147,8 @@ valid_flags() ->
|
||||||
].
|
].
|
||||||
|
|
||||||
|
|
||||||
|
-spec extract_config(Config::proplists:proplist()) -> proplists:proplist().
|
||||||
|
|
||||||
extract_config(Config) ->
|
extract_config(Config) ->
|
||||||
extract_parser_config(Config, []).
|
extract_parser_config(Config, []).
|
||||||
|
|
||||||
|
@ -281,4 +301,4 @@ config_to_list_test_() ->
|
||||||
fake_error_handler(_, _, _) -> ok.
|
fake_error_handler(_, _, _) -> ok.
|
||||||
|
|
||||||
|
|
||||||
-endif.
|
-endif.
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
-record(config, {
|
-record(config, {
|
||||||
escaped_forward_slashes = false,
|
escaped_forward_slashes = false :: boolean(),
|
||||||
escaped_strings = false,
|
escaped_strings = false :: boolean(),
|
||||||
unescaped_jsonp = false,
|
unescaped_jsonp = false :: boolean(),
|
||||||
dirty_strings = false,
|
dirty_strings = false :: boolean(),
|
||||||
strict_comments = false,
|
strict_comments = false :: boolean(),
|
||||||
strict_utf8 = false,
|
strict_utf8 = false :: boolean(),
|
||||||
strict_single_quotes = false,
|
strict_single_quotes = false :: boolean(),
|
||||||
strict_escapes = false,
|
strict_escapes = false :: boolean(),
|
||||||
stream = false,
|
stream = false :: boolean(),
|
||||||
error_handler = false,
|
error_handler = false :: false | jsx_config:handler(),
|
||||||
incomplete_handler = false
|
incomplete_handler = false :: false | jsx_config:handler()
|
||||||
}).
|
}).
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
-export([decoder/3, resume/6]).
|
-export([decoder/3, resume/6]).
|
||||||
|
|
||||||
|
|
||||||
-spec decoder(Handler::module(), State::any(), Config::jsx:config()) -> jsx:decoder().
|
-spec decoder(Handler::module(), State::any(), Config::list()) -> jsx:decoder().
|
||||||
|
|
||||||
decoder(Handler, State, Config) ->
|
decoder(Handler, State, Config) ->
|
||||||
fun(JSON) -> start(JSON, {Handler, Handler:init(State)}, [], jsx_config:parse_config(Config)) end.
|
fun(JSON) -> start(JSON, {Handler, Handler:init(State)}, [], jsx_config:parse_config(Config)) end.
|
||||||
|
@ -48,7 +48,7 @@ decoder(Handler, State, Config) ->
|
||||||
Acc::any(),
|
Acc::any(),
|
||||||
Stack::list(atom()),
|
Stack::list(atom()),
|
||||||
Config::jsx:config()
|
Config::jsx:config()
|
||||||
) -> jsx:decoder().
|
) -> jsx:decoder() | {incomplete, jsx:decoder()}.
|
||||||
|
|
||||||
resume(Rest, State, Handler, Acc, Stack, Config) ->
|
resume(Rest, State, Handler, Acc, Stack, Config) ->
|
||||||
case State of
|
case State of
|
||||||
|
@ -671,12 +671,12 @@ unescape(<<$u, $d, A, B, C, ?rsolidus, $u, W, X, Y, Z, Rest/binary>>, Handler, A
|
||||||
false -> string(Rest, Handler, acc_seq(Acc, [16#fffd, 16#fffd]), Stack, Config)
|
false -> string(Rest, Handler, acc_seq(Acc, [16#fffd, 16#fffd]), Stack, Config)
|
||||||
end;
|
end;
|
||||||
unescape(<<$u, $d, A, B, C, ?rsolidus, Rest/binary>>, Handler, Acc, Stack, Config)
|
unescape(<<$u, $d, A, B, C, ?rsolidus, Rest/binary>>, Handler, Acc, Stack, Config)
|
||||||
when (A == $8 orelse A == $9 orelse A == $a orelse A == $b) andalso
|
when (A == $8 orelse A == $9 orelse A == $a orelse A == $b),
|
||||||
?is_hex(B), ?is_hex(C)
|
?is_hex(B), ?is_hex(C)
|
||||||
->
|
->
|
||||||
incomplete(string, <<?rsolidus, $u, $d, A, B, C, ?rsolidus, Rest/binary>>, Handler, Acc, Stack, Config);
|
incomplete(string, <<?rsolidus, $u, $d, A, B, C, ?rsolidus, Rest/binary>>, Handler, Acc, Stack, Config);
|
||||||
unescape(<<$u, $d, A, B, C>>, Handler, Acc, Stack, Config)
|
unescape(<<$u, $d, A, B, C>>, Handler, Acc, Stack, Config)
|
||||||
when (A == $8 orelse A == $9 orelse A == $a orelse A == $b) andalso
|
when (A == $8 orelse A == $9 orelse A == $a orelse A == $b),
|
||||||
?is_hex(B), ?is_hex(C)
|
?is_hex(B), ?is_hex(C)
|
||||||
->
|
->
|
||||||
incomplete(string, <<?rsolidus, $u, $d, A, B, C>>, Handler, Acc, Stack, Config);
|
incomplete(string, <<?rsolidus, $u, $d, A, B, C>>, Handler, Acc, Stack, Config);
|
||||||
|
@ -1687,4 +1687,4 @@ custom_incomplete_handler_test_() ->
|
||||||
].
|
].
|
||||||
|
|
||||||
|
|
||||||
-endif.
|
-endif.
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
-export([encoder/3, encode/1, encode/2, unzip/1]).
|
-export([encoder/3, encode/1, encode/2, unzip/1]).
|
||||||
|
|
||||||
-spec encoder(Handler::module(), State::any(), Config::jsx:config()) -> jsx:encoder().
|
-spec encoder(Handler::module(), State::any(), Config::list()) -> jsx:encoder().
|
||||||
|
|
||||||
encoder(Handler, State, Config) ->
|
encoder(Handler, State, Config) ->
|
||||||
Parser = jsx:parser(Handler, State, Config),
|
Parser = jsx:parser(Handler, State, Config),
|
||||||
|
@ -57,8 +57,7 @@ encode(Else, _EntryPoint) -> [Else].
|
||||||
unzip(List) -> unzip(List, []).
|
unzip(List) -> unzip(List, []).
|
||||||
|
|
||||||
unzip([], Acc) -> lists:reverse(Acc);
|
unzip([], Acc) -> lists:reverse(Acc);
|
||||||
unzip([{K, V}|Rest], Acc) when is_binary(K); is_atom(K) -> unzip(Rest, [V, K] ++ Acc).
|
unzip([{K, V}|Rest], Acc) when is_binary(K); is_atom(K); is_integer(K) -> unzip(Rest, [V, K] ++ Acc).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-ifdef(TEST).
|
-ifdef(TEST).
|
||||||
|
@ -67,6 +66,7 @@ unzip([{K, V}|Rest], Acc) when is_binary(K); is_atom(K) -> unzip(Rest, [V, K] ++
|
||||||
|
|
||||||
parser(Term, Opts) -> (jsx:parser(jsx, [], Opts))(Term).
|
parser(Term, Opts) -> (jsx:parser(jsx, [], Opts))(Term).
|
||||||
|
|
||||||
|
|
||||||
error_test_() ->
|
error_test_() ->
|
||||||
[
|
[
|
||||||
{"value error", ?_assertError(badarg, parser(self(), []))},
|
{"value error", ?_assertError(badarg, parser(self(), []))},
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
-export([init/1, handle_event/2]).
|
-export([init/1, handle_event/2]).
|
||||||
|
|
||||||
|
|
||||||
-spec parser(Handler::module(), State::any(), Config::jsx:config()) -> jsx:parser().
|
-spec parser(Handler::module(), State::any(), Config::list()) -> jsx:parser().
|
||||||
|
|
||||||
parser(Handler, State, Config) ->
|
parser(Handler, State, Config) ->
|
||||||
fun(Tokens) -> value(Tokens, {Handler, Handler:init(State)}, [], jsx_config:parse_config(Config)) end.
|
fun(Tokens) -> value(Tokens, {Handler, Handler:init(State)}, [], jsx_config:parse_config(Config)) end.
|
||||||
|
@ -36,12 +36,12 @@ parser(Handler, State, Config) ->
|
||||||
%% resume allows continuation from interrupted decoding without having to explicitly export
|
%% resume allows continuation from interrupted decoding without having to explicitly export
|
||||||
%% all states
|
%% all states
|
||||||
-spec resume(
|
-spec resume(
|
||||||
Rest::binary(),
|
Rest::jsx:token(),
|
||||||
State::atom(),
|
State::atom(),
|
||||||
Handler::{atom(), any()},
|
Handler::{atom(), any()},
|
||||||
Stack::list(atom()),
|
Stack::list(atom()),
|
||||||
Config::jsx:config()
|
Config::jsx:config()
|
||||||
) -> jsx:parser().
|
) -> jsx:parser() | {incomplete, jsx:parser()}.
|
||||||
|
|
||||||
resume(Rest, State, Handler, Stack, Config) ->
|
resume(Rest, State, Handler, Stack, Config) ->
|
||||||
case State of
|
case State of
|
||||||
|
@ -84,8 +84,6 @@ incomplete(State, Handler, Stack, Config=#config{incomplete_handler=F}) ->
|
||||||
F([], {parser, State, Handler, Stack}, jsx_config:config_to_list(Config)).
|
F([], {parser, State, Handler, Stack}, jsx_config:config_to_list(Config)).
|
||||||
|
|
||||||
|
|
||||||
handle_event([], Handler, _Config) -> Handler;
|
|
||||||
handle_event([Event|Rest], Handler, Config) -> handle_event(Rest, handle_event(Event, Handler, Config), Config);
|
|
||||||
handle_event(Event, {Handler, State}, _Config) -> {Handler, Handler:handle_event(Event, State)}.
|
handle_event(Event, {Handler, State}, _Config) -> {Handler, Handler:handle_event(Event, State)}.
|
||||||
|
|
||||||
|
|
||||||
|
@ -128,13 +126,13 @@ value(Token, Handler, Stack, Config) ->
|
||||||
|
|
||||||
object([end_object|Tokens], Handler, [object|Stack], Config) ->
|
object([end_object|Tokens], Handler, [object|Stack], Config) ->
|
||||||
maybe_done(Tokens, handle_event(end_object, Handler, Config), Stack, Config);
|
maybe_done(Tokens, handle_event(end_object, Handler, Config), Stack, Config);
|
||||||
object([{key, Key}|Tokens], Handler, Stack, Config) when is_atom(Key); is_binary(Key) ->
|
object([{key, Key}|Tokens], Handler, Stack, Config) when is_atom(Key); is_binary(Key); is_integer(Key) ->
|
||||||
case clean_string(fix_key(Key), Tokens, Handler, Stack, Config) of
|
case clean_string(fix_key(Key), Tokens, Handler, Stack, Config) of
|
||||||
Clean when is_binary(Clean) ->
|
Clean when is_binary(Clean) ->
|
||||||
value(Tokens, handle_event({key, Clean}, Handler, Config), Stack, Config);
|
value(Tokens, handle_event({key, Clean}, Handler, Config), Stack, Config);
|
||||||
Error -> Error
|
Error -> Error
|
||||||
end;
|
end;
|
||||||
object([Key|Tokens], Handler, Stack, Config) when is_atom(Key); is_binary(Key) ->
|
object([Key|Tokens], Handler, Stack, Config) when is_atom(Key); is_binary(Key); is_integer(Key) ->
|
||||||
case clean_string(fix_key(Key), Tokens, Handler, Stack, Config) of
|
case clean_string(fix_key(Key), Tokens, Handler, Stack, Config) of
|
||||||
Clean when is_binary(Clean) ->
|
Clean when is_binary(Clean) ->
|
||||||
value(Tokens, handle_event({key, Clean}, Handler, Config), Stack, Config);
|
value(Tokens, handle_event({key, Clean}, Handler, Config), Stack, Config);
|
||||||
|
@ -178,7 +176,8 @@ done(Token, Handler, Stack, Config) ->
|
||||||
done([Token], Handler, Stack, Config).
|
done([Token], Handler, Stack, Config).
|
||||||
|
|
||||||
|
|
||||||
fix_key(Key) when is_atom(Key) -> fix_key(atom_to_binary(Key, utf8));
|
fix_key(Key) when is_atom(Key) -> atom_to_binary(Key, utf8);
|
||||||
|
fix_key(Key) when is_integer(Key) -> list_to_binary(integer_to_list(Key));
|
||||||
fix_key(Key) when is_binary(Key) -> Key.
|
fix_key(Key) when is_binary(Key) -> Key.
|
||||||
|
|
||||||
|
|
||||||
|
@ -440,8 +439,12 @@ to_hex(X) -> X + 48. %% ascii "1" is [49], "2" is [50], etc...
|
||||||
|
|
||||||
|
|
||||||
%% for raw input
|
%% for raw input
|
||||||
|
-spec init(proplists:proplist()) -> list().
|
||||||
|
|
||||||
init([]) -> [].
|
init([]) -> [].
|
||||||
|
|
||||||
|
-spec handle_event(Event::any(), Acc::list()) -> list().
|
||||||
|
|
||||||
handle_event(end_json, State) -> lists:reverse(State);
|
handle_event(end_json, State) -> lists:reverse(State);
|
||||||
handle_event(Event, State) -> [Event] ++ State.
|
handle_event(Event, State) -> [Event] ++ State.
|
||||||
|
|
||||||
|
@ -997,4 +1000,11 @@ json_escape_sequence_test_() ->
|
||||||
].
|
].
|
||||||
|
|
||||||
|
|
||||||
-endif.
|
fix_key_test_() ->
|
||||||
|
[
|
||||||
|
{"binary key", ?_assertEqual(fix_key(<<"foo">>), <<"foo">>)},
|
||||||
|
{"atom key", ?_assertEqual(fix_key(foo), <<"foo">>)},
|
||||||
|
{"integer key", ?_assertEqual(fix_key(123), <<"123">>)}
|
||||||
|
].
|
||||||
|
|
||||||
|
-endif.
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
}).
|
}).
|
||||||
|
|
||||||
-type config() :: list().
|
-type config() :: list().
|
||||||
|
-export_type([config/0]).
|
||||||
|
|
||||||
|
|
||||||
-spec to_json(Source::any(), Config::config()) -> binary().
|
-spec to_json(Source::any(), Config::config()) -> binary().
|
||||||
|
@ -85,9 +86,14 @@ parse_config([], Config) ->
|
||||||
-define(newline, <<"\n">>).
|
-define(newline, <<"\n">>).
|
||||||
|
|
||||||
|
|
||||||
|
-type state() :: {unicode:charlist(), #config{}}.
|
||||||
|
-spec init(Config::proplists:proplist()) -> state().
|
||||||
|
|
||||||
init(Config) -> {[], parse_config(Config)}.
|
init(Config) -> {[], parse_config(Config)}.
|
||||||
|
|
||||||
|
|
||||||
|
-spec handle_event(Event::any(), State::state()) -> state().
|
||||||
|
|
||||||
handle_event(end_json, {Term, _Config}) -> Term;
|
handle_event(end_json, {Term, _Config}) -> Term;
|
||||||
|
|
||||||
handle_event(start_object, State) -> start_object(State);
|
handle_event(start_object, State) -> start_object(State);
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
}).
|
}).
|
||||||
|
|
||||||
-type config() :: list().
|
-type config() :: list().
|
||||||
|
-export_type([config/0]).
|
||||||
|
|
||||||
|
|
||||||
-type json_value() :: list({binary(), json_value()})
|
-type json_value() :: list({binary(), json_value()})
|
||||||
| list(json_value())
|
| list(json_value())
|
||||||
|
@ -70,9 +72,12 @@ parse_config([K|Rest] = Options, Config) ->
|
||||||
parse_config([], Config) ->
|
parse_config([], Config) ->
|
||||||
Config.
|
Config.
|
||||||
|
|
||||||
|
-type state() :: {[any()], #config{}}.
|
||||||
|
-spec init(Config::proplists:proplist()) -> state().
|
||||||
|
|
||||||
init(Config) -> {[], parse_config(Config)}.
|
init(Config) -> {[], parse_config(Config)}.
|
||||||
|
|
||||||
|
-spec handle_event(Event::any(), State::state()) -> state().
|
||||||
|
|
||||||
handle_event(end_json, {Term, _Config}) -> Term;
|
handle_event(end_json, {Term, _Config}) -> Term;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
}).
|
}).
|
||||||
|
|
||||||
-type config() :: [].
|
-type config() :: [].
|
||||||
|
-export_type([config/0]).
|
||||||
|
|
||||||
|
|
||||||
-spec is_json(Source::binary(), Config::config()) -> true | false.
|
-spec is_json(Source::binary(), Config::config()) -> true | false.
|
||||||
|
@ -72,10 +73,14 @@ parse_config([K|Rest] = Options, Config) ->
|
||||||
parse_config([], Config) ->
|
parse_config([], Config) ->
|
||||||
Config.
|
Config.
|
||||||
|
|
||||||
|
-type state() :: {#config{}, any()}.
|
||||||
|
-spec init(Config::proplists:proplist()) -> state().
|
||||||
|
|
||||||
init(Config) -> {parse_config(Config), []}.
|
init(Config) -> {parse_config(Config), []}.
|
||||||
|
|
||||||
|
|
||||||
|
-spec handle_event(Event::any(), State::state()) -> state().
|
||||||
|
|
||||||
handle_event(end_json, _) -> true;
|
handle_event(end_json, _) -> true;
|
||||||
|
|
||||||
handle_event(_, {Config, _} = State) when Config#config.repeated_keys == true -> State;
|
handle_event(_, {Config, _} = State) when Config#config.repeated_keys == true -> State;
|
||||||
|
@ -165,4 +170,4 @@ handle_event_test_() ->
|
||||||
].
|
].
|
||||||
|
|
||||||
|
|
||||||
-endif.
|
-endif.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue