refactors out extraction of parser opts, generalizes use of specific parsers by processors
This commit is contained in:
parent
55d0259c89
commit
6dacf64620
7 changed files with 57 additions and 80 deletions
|
@ -1,5 +1,6 @@
|
||||||
-record(opts, {
|
-record(opts, {
|
||||||
loose_unicode = false,
|
loose_unicode = false,
|
||||||
escape_forward_slash = false,
|
escape_forward_slash = false,
|
||||||
explicit_end = false
|
explicit_end = false,
|
||||||
|
parser = auto
|
||||||
}).
|
}).
|
|
@ -33,6 +33,14 @@ behaviour_info(_) -> undefined.
|
||||||
|
|
||||||
parser(Mod, Args) -> parser(Mod, Args, []).
|
parser(Mod, Args) -> parser(Mod, Args, []).
|
||||||
|
|
||||||
parser(Mod, Args, Opts) -> fun(Input) when is_list(Input) -> (jsx:encoder(Mod, Args, Opts))(Input)
|
parser(Mod, Args, Opts) when is_atom(Mod), is_list(Opts) ->
|
||||||
; (Input) when is_binary(Input) -> (jsx:decoder(Mod, Args, Opts))(Input)
|
case proplists:get_value(parser, Opts, auto) of
|
||||||
|
auto ->
|
||||||
|
fun(Input) when is_list(Input) -> (jsx:encoder(Mod, Args, Opts))(Input)
|
||||||
|
; (Input) when is_binary(Input) -> (jsx:decoder(Mod, Args, Opts))(Input)
|
||||||
|
end
|
||||||
|
; encoder ->
|
||||||
|
fun(Input) -> (jsx:encoder(Mod, Args, Opts))(Input) end
|
||||||
|
; decoder ->
|
||||||
|
fun(Input) -> (jsx:decoder(Mod, Args, Opts))(Input) end
|
||||||
end.
|
end.
|
37
src/jsx.erl
37
src/jsx.erl
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
-module(jsx).
|
-module(jsx).
|
||||||
|
|
||||||
-export([encoder/0, encoder/1]).
|
-export([encoder/2, encoder/3]).
|
||||||
-export([decoder/2, decoder/3]).
|
-export([decoder/2, decoder/3]).
|
||||||
%% shims for jsx_to_json, jsx_to_term, jsx_verify
|
%% shims for jsx_to_json, jsx_to_term, jsx_verify
|
||||||
-export([to_json/1, to_json/2]).
|
-export([to_json/1, to_json/2]).
|
||||||
|
@ -56,7 +56,10 @@
|
||||||
-include("../include/jsx_opts.hrl").
|
-include("../include/jsx_opts.hrl").
|
||||||
|
|
||||||
-type opts() :: [opt()].
|
-type opts() :: [opt()].
|
||||||
-type opt() :: loose_unicode | escape_forward_slashes | explicit_end.
|
-type opt() :: loose_unicode
|
||||||
|
| escape_forward_slashes
|
||||||
|
| explicit_end
|
||||||
|
| {parser, auto} | {parser, encoder} | {parser, decoder} | {parser, function()}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,20 +68,22 @@
|
||||||
-spec decoder(Mod::module(), Args::any()) -> decoder().
|
-spec decoder(Mod::module(), Args::any()) -> decoder().
|
||||||
-spec decoder(Mod::module(), Args::any(), OptsList::opts()) -> decoder().
|
-spec decoder(Mod::module(), Args::any(), OptsList::opts()) -> decoder().
|
||||||
|
|
||||||
decoder(Mod, Args) -> decoder(Mod, Args, []).
|
decoder(Mod, Args) when is_atom(Mod) -> decoder(Mod, Args, []).
|
||||||
|
|
||||||
decoder(Mod, Args, OptsList) when is_list(OptsList) -> jsx_decoder:decoder(Mod, Args, OptsList).
|
decoder(Mod, Args, OptsList) when is_atom(Mod), is_list(OptsList) ->
|
||||||
|
jsx_decoder:decoder(Mod, Args, OptsList).
|
||||||
|
|
||||||
|
|
||||||
-type encoder() :: fun((list()) ->
|
-type encoder() :: fun((list()) ->
|
||||||
{ok, events()} | {incomplete, decoder()}).
|
{ok, events()} | {incomplete, decoder()}).
|
||||||
|
|
||||||
-spec encoder() -> encoder().
|
-spec encoder(Mod::module(), Args::any()) -> encoder().
|
||||||
-spec encoder(OptsList::opts()) -> encoder().
|
-spec encoder(Mod::module(), Args::any(), OptsList::opts()) -> encoder().
|
||||||
|
|
||||||
encoder() -> encoder([]).
|
encoder(Mod, Args) when is_atom(Mod) -> encoder(Mod, Args, []).
|
||||||
|
|
||||||
encoder(OptsList) when is_list(OptsList) -> jsx_encoder:encoder(OptsList).
|
encoder(Mod, Args, OptsList) when is_atom(Mod), is_list(OptsList) ->
|
||||||
|
jsx_encoder:encoder(Mod, Args, OptsList).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -120,21 +125,7 @@ encoder_decoder_equiv_test_() ->
|
||||||
{"encoder/decoder equivalency",
|
{"encoder/decoder equivalency",
|
||||||
?_assert((jsx:decoder(?MODULE, []))(
|
?_assert((jsx:decoder(?MODULE, []))(
|
||||||
<<"[\"a\", 17, 3.14, true, {\"k\":false}, []]">>
|
<<"[\"a\", 17, 3.14, true, {\"k\":false}, []]">>
|
||||||
) =:= (jsx:encoder())(
|
) =:= (jsx:encoder(?MODULE, []))([<<"a">>, 17, 3.14, true, [{<<"k">>, false}], []])
|
||||||
[start_array,
|
|
||||||
{string, <<"a">>},
|
|
||||||
{integer, 17},
|
|
||||||
{float, 3.14},
|
|
||||||
{literal, true},
|
|
||||||
start_object,
|
|
||||||
{key, <<"k">>},
|
|
||||||
{literal, false},
|
|
||||||
end_object,
|
|
||||||
start_array,
|
|
||||||
end_array,
|
|
||||||
end_array,
|
|
||||||
end_json]
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
].
|
].
|
||||||
|
|
|
@ -40,13 +40,10 @@
|
||||||
|
|
||||||
to_json(Source, Opts) when (is_binary(Source) andalso is_list(Opts))
|
to_json(Source, Opts) when (is_binary(Source) andalso is_list(Opts))
|
||||||
orelse (is_list(Source) andalso is_list(Opts)) ->
|
orelse (is_list(Source) andalso is_list(Opts)) ->
|
||||||
(gen_json:parser(?MODULE, Opts, extract_opts(Opts)))(Source).
|
(gen_json:parser(?MODULE, Opts, jsx_utils:extract_opts(Opts)))(Source).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
init(Opts) -> {start, [], parse_opts(Opts)}.
|
|
||||||
|
|
||||||
|
|
||||||
parse_opts(Opts) -> parse_opts(Opts, #opts{}).
|
parse_opts(Opts) -> parse_opts(Opts, #opts{}).
|
||||||
|
|
||||||
parse_opts([{space, Val}|Rest], Opts) when is_integer(Val), Val > 0 ->
|
parse_opts([{space, Val}|Rest], Opts) when is_integer(Val), Val > 0 ->
|
||||||
|
@ -63,21 +60,6 @@ parse_opts([], Opts) ->
|
||||||
Opts.
|
Opts.
|
||||||
|
|
||||||
|
|
||||||
extract_opts(Opts) ->
|
|
||||||
extract_parser_opts(Opts, []).
|
|
||||||
|
|
||||||
extract_parser_opts([], Acc) -> Acc;
|
|
||||||
extract_parser_opts([{K,V}|Rest], Acc) ->
|
|
||||||
case lists:member(K, [loose_unicode, escape_forward_slash, explicit_end]) of
|
|
||||||
true -> extract_parser_opts(Rest, [{K,V}] ++ Acc)
|
|
||||||
; false -> extract_parser_opts(Rest, Acc)
|
|
||||||
end;
|
|
||||||
extract_parser_opts([K|Rest], Acc) ->
|
|
||||||
case lists:member(K, [loose_unicode, escape_forward_slash, explicit_end]) of
|
|
||||||
true -> extract_parser_opts(Rest, [K] ++ Acc)
|
|
||||||
; false -> extract_parser_opts(Rest, Acc)
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
-define(start_object, <<"{">>).
|
-define(start_object, <<"{">>).
|
||||||
-define(start_array, <<"[">>).
|
-define(start_array, <<"[">>).
|
||||||
|
@ -90,6 +72,11 @@ extract_parser_opts([K|Rest], Acc) ->
|
||||||
-define(newline, <<"\n">>).
|
-define(newline, <<"\n">>).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
init(Opts) -> {start, [], parse_opts(Opts)}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
handle_event(Event, {start, Acc, Opts}) ->
|
handle_event(Event, {start, Acc, Opts}) ->
|
||||||
case Event of
|
case Event of
|
||||||
{Type, Value} -> {[], [Acc, encode(Type, Value)], Opts}
|
{Type, Value} -> {[], [Acc, encode(Type, Value)], Opts}
|
||||||
|
|
|
@ -38,13 +38,10 @@
|
||||||
|
|
||||||
to_term(Source, Opts) when (is_binary(Source) andalso is_list(Opts))
|
to_term(Source, Opts) when (is_binary(Source) andalso is_list(Opts))
|
||||||
orelse (is_list(Source) andalso is_list(Opts)) ->
|
orelse (is_list(Source) andalso is_list(Opts)) ->
|
||||||
(gen_json:parser(?MODULE, Opts, extract_opts(Opts)))(Source).
|
(gen_json:parser(?MODULE, Opts, jsx_utils:extract_opts(Opts)))(Source).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
init(Opts) -> {[[]], parse_opts(Opts)}.
|
|
||||||
|
|
||||||
|
|
||||||
parse_opts(Opts) -> parse_opts(Opts, #opts{}).
|
parse_opts(Opts) -> parse_opts(Opts, #opts{}).
|
||||||
|
|
||||||
parse_opts([{labels, Val}|Rest], Opts)
|
parse_opts([{labels, Val}|Rest], Opts)
|
||||||
|
@ -58,20 +55,9 @@ parse_opts([], Opts) ->
|
||||||
Opts.
|
Opts.
|
||||||
|
|
||||||
|
|
||||||
extract_opts(Opts) ->
|
|
||||||
extract_parser_opts(Opts, []).
|
|
||||||
|
|
||||||
extract_parser_opts([], Acc) -> Acc;
|
init(Opts) -> {[[]], parse_opts(Opts)}.
|
||||||
extract_parser_opts([{K,V}|Rest], Acc) ->
|
|
||||||
case lists:member(K, [loose_unicode, escape_forward_slash, explicit_end]) of
|
|
||||||
true -> extract_parser_opts(Rest, [{K,V}] ++ Acc)
|
|
||||||
; false -> extract_parser_opts(Rest, Acc)
|
|
||||||
end;
|
|
||||||
extract_parser_opts([K|Rest], Acc) ->
|
|
||||||
case lists:member(K, [loose_unicode, escape_forward_slash, explicit_end]) of
|
|
||||||
true -> extract_parser_opts(Rest, [K] ++ Acc)
|
|
||||||
; false -> extract_parser_opts(Rest, Acc)
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
handle_event(end_json, {[[Terms]], _Opts}) -> Terms;
|
handle_event(end_json, {[[Terms]], _Opts}) -> Terms;
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
-module(jsx_utils).
|
-module(jsx_utils).
|
||||||
|
|
||||||
-export([parse_opts/1, nice_decimal/1, json_escape/2]).
|
-export([parse_opts/1, extract_opts/1, nice_decimal/1, json_escape/2]).
|
||||||
|
|
||||||
-include("../include/jsx_opts.hrl").
|
-include("../include/jsx_opts.hrl").
|
||||||
|
|
||||||
|
@ -41,10 +41,28 @@ parse_opts([escape_forward_slash|Rest], Opts) ->
|
||||||
parse_opts(Rest, Opts#opts{escape_forward_slash=true});
|
parse_opts(Rest, Opts#opts{escape_forward_slash=true});
|
||||||
parse_opts([explicit_end|Rest], Opts) ->
|
parse_opts([explicit_end|Rest], Opts) ->
|
||||||
parse_opts(Rest, Opts#opts{explicit_end=true});
|
parse_opts(Rest, Opts#opts{explicit_end=true});
|
||||||
|
parse_opts([{parser, Mode}|Rest], Opts) ->
|
||||||
|
parse_opts(Rest, Opts#opts{parser=Mode});
|
||||||
parse_opts(_, _) ->
|
parse_opts(_, _) ->
|
||||||
{error, badarg}.
|
{error, badarg}.
|
||||||
|
|
||||||
|
|
||||||
|
extract_opts(Opts) ->
|
||||||
|
extract_parser_opts(Opts, []).
|
||||||
|
|
||||||
|
extract_parser_opts([], Acc) -> Acc;
|
||||||
|
extract_parser_opts([{K,V}|Rest], Acc) ->
|
||||||
|
case lists:member(K, [loose_unicode, escape_forward_slash, explicit_end, parser]) of
|
||||||
|
true -> extract_parser_opts(Rest, [{K,V}] ++ Acc)
|
||||||
|
; false -> extract_parser_opts(Rest, Acc)
|
||||||
|
end;
|
||||||
|
extract_parser_opts([K|Rest], Acc) ->
|
||||||
|
case lists:member(K, [loose_unicode, escape_forward_slash, explicit_end]) of
|
||||||
|
true -> extract_parser_opts(Rest, [K] ++ Acc)
|
||||||
|
; false -> extract_parser_opts(Rest, Acc)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
%% conversion of floats to 'nice' decimal output. erlang's float implementation
|
%% conversion of floats to 'nice' decimal output. erlang's float implementation
|
||||||
%% is almost but not quite ieee 754. it converts negative zero to plain zero
|
%% is almost but not quite ieee 754. it converts negative zero to plain zero
|
||||||
%% silently, and throws exceptions for any operations that would produce NaN
|
%% silently, and throws exceptions for any operations that would produce NaN
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
is_json(Source, Opts) when (is_binary(Source) andalso is_list(Opts))
|
is_json(Source, Opts) when (is_binary(Source) andalso is_list(Opts))
|
||||||
orelse (is_list(Source) andalso is_list(Opts)) ->
|
orelse (is_list(Source) andalso is_list(Opts)) ->
|
||||||
try case (gen_json:parser(?MODULE, Opts, extract_opts(Opts)))(Source) of
|
try case (gen_json:parser(?MODULE, Opts, jsx_utils:extract_opts(Opts)))(Source) of
|
||||||
{incomplete, _} -> false
|
{incomplete, _} -> false
|
||||||
; true -> true
|
; true -> true
|
||||||
end
|
end
|
||||||
|
@ -47,9 +47,6 @@ is_json(Source, Opts) when (is_binary(Source) andalso is_list(Opts))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
init(Opts) -> {parse_opts(Opts), []}.
|
|
||||||
|
|
||||||
|
|
||||||
parse_opts(Opts) -> parse_opts(Opts, #opts{}).
|
parse_opts(Opts) -> parse_opts(Opts, #opts{}).
|
||||||
|
|
||||||
parse_opts([{repeated_keys, Val}|Rest], Opts) when Val == true; Val == false ->
|
parse_opts([{repeated_keys, Val}|Rest], Opts) when Val == true; Val == false ->
|
||||||
|
@ -62,20 +59,9 @@ parse_opts([], Opts) ->
|
||||||
Opts.
|
Opts.
|
||||||
|
|
||||||
|
|
||||||
extract_opts(Opts) ->
|
|
||||||
extract_parser_opts(Opts, []).
|
|
||||||
|
|
||||||
extract_parser_opts([], Acc) -> Acc;
|
init(Opts) -> {parse_opts(Opts), []}.
|
||||||
extract_parser_opts([{K,V}|Rest], Acc) ->
|
|
||||||
case lists:member(K, [loose_unicode, escape_forward_slash, explicit_end]) of
|
|
||||||
true -> extract_parser_opts(Rest, [{K,V}] ++ Acc)
|
|
||||||
; false -> extract_parser_opts(Rest, Acc)
|
|
||||||
end;
|
|
||||||
extract_parser_opts([K|Rest], Acc) ->
|
|
||||||
case lists:member(K, [loose_unicode, escape_forward_slash, explicit_end]) of
|
|
||||||
true -> extract_parser_opts(Rest, [K] ++ Acc)
|
|
||||||
; false -> extract_parser_opts(Rest, Acc)
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
handle_event(end_json, _) -> true;
|
handle_event(end_json, _) -> true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue