add a return_maps
option that returns maps instead of proplists
This commit is contained in:
parent
55eaa7b524
commit
989609b250
1 changed files with 62 additions and 8 deletions
|
@ -30,7 +30,8 @@
|
||||||
|
|
||||||
|
|
||||||
-record(config, {
|
-record(config, {
|
||||||
labels = binary
|
labels = binary,
|
||||||
|
return_maps = false
|
||||||
}).
|
}).
|
||||||
|
|
||||||
-type config() :: list().
|
-type config() :: list().
|
||||||
|
@ -60,6 +61,11 @@ parse_config([{labels, Val}|Rest], Config)
|
||||||
parse_config(Rest, Config#config{labels = Val});
|
parse_config(Rest, Config#config{labels = Val});
|
||||||
parse_config([labels|Rest], Config) ->
|
parse_config([labels|Rest], Config) ->
|
||||||
parse_config(Rest, Config#config{labels = binary});
|
parse_config(Rest, Config#config{labels = binary});
|
||||||
|
parse_config([{return_maps, Val}|Rest], Config)
|
||||||
|
when Val == true; Val == false ->
|
||||||
|
parse_config(Rest, Config#config{return_maps = true});
|
||||||
|
parse_config([return_maps|Rest], Config) ->
|
||||||
|
parse_config(Rest, Config#config{return_maps = true});
|
||||||
parse_config([{K, _}|Rest] = Options, Config) ->
|
parse_config([{K, _}|Rest] = Options, Config) ->
|
||||||
case lists:member(K, jsx_config:valid_flags()) of
|
case lists:member(K, jsx_config:valid_flags()) of
|
||||||
true -> parse_config(Rest, Config)
|
true -> parse_config(Rest, Config)
|
||||||
|
@ -128,15 +134,31 @@ start_object({Stack, Config}) -> {[{object, []}] ++ Stack, Config}.
|
||||||
%% allocate a new array on top of the stack
|
%% allocate a new array on top of the stack
|
||||||
start_array({Stack, Config}) -> {[{array, []}] ++ Stack, Config}.
|
start_array({Stack, Config}) -> {[{array, []}] ++ Stack, Config}.
|
||||||
|
|
||||||
|
-ifndef(maps_support).
|
||||||
|
finish(Any) -> finish0(Any).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifdef(maps_support).
|
||||||
|
finish({[{object, []}], Config=#config{return_maps=true}}) ->
|
||||||
|
{#{}, Config};
|
||||||
|
finish({[{object, []}|Rest], Config=#config{return_maps=true}}) ->
|
||||||
|
insert(#{}, {Rest, Config});
|
||||||
|
finish({[{object, Pairs}], Config=#config{return_maps=true}}) ->
|
||||||
|
{maps:from_list(Pairs), Config};
|
||||||
|
finish({[{object, Pairs}|Rest], Config=#config{return_maps=true}}) ->
|
||||||
|
insert(maps:from_list(Pairs), {Rest, Config});
|
||||||
|
finish(Else) -> finish0(Else).
|
||||||
|
-endif.
|
||||||
|
|
||||||
%% finish an object or array and insert it into the parent object if it exists or
|
%% finish an object or array and insert it into the parent object if it exists or
|
||||||
%% return it if it is the root object
|
%% return it if it is the root object
|
||||||
finish({[{object, []}], Config}) -> {[{}], Config};
|
finish0({[{object, []}], Config}) -> {[{}], Config};
|
||||||
finish({[{object, []}|Rest], Config}) -> insert([{}], {Rest, Config});
|
finish0({[{object, []}|Rest], Config}) -> insert([{}], {Rest, Config});
|
||||||
finish({[{object, Pairs}], Config}) -> {lists:reverse(Pairs), Config};
|
finish0({[{object, Pairs}], Config}) -> {lists:reverse(Pairs), Config};
|
||||||
finish({[{object, Pairs}|Rest], Config}) -> insert(lists:reverse(Pairs), {Rest, Config});
|
finish0({[{object, Pairs}|Rest], Config}) -> insert(lists:reverse(Pairs), {Rest, Config});
|
||||||
finish({[{array, Values}], Config}) -> {lists:reverse(Values), Config};
|
finish0({[{array, Values}], Config}) -> {lists:reverse(Values), Config};
|
||||||
finish({[{array, Values}|Rest], Config}) -> insert(lists:reverse(Values), {Rest, Config});
|
finish0({[{array, Values}|Rest], Config}) -> insert(lists:reverse(Values), {Rest, Config});
|
||||||
finish(_) -> erlang:error(badarg).
|
finish0(_) -> erlang:error(badarg).
|
||||||
|
|
||||||
%% insert a value when there's no parent object or array
|
%% insert a value when there's no parent object or array
|
||||||
insert(Value, {[], Config}) -> {Value, Config};
|
insert(Value, {[], Config}) -> {Value, Config};
|
||||||
|
@ -179,6 +201,10 @@ config_test_() ->
|
||||||
#config{labels=existing_atom},
|
#config{labels=existing_atom},
|
||||||
parse_config([{labels, existing_atom}])
|
parse_config([{labels, existing_atom}])
|
||||||
)},
|
)},
|
||||||
|
{"return_maps true", ?_assertEqual(
|
||||||
|
#config{return_maps=true},
|
||||||
|
parse_config([return_maps])
|
||||||
|
)},
|
||||||
{"invalid opt flag", ?_assertError(badarg, parse_config([error]))},
|
{"invalid opt flag", ?_assertError(badarg, parse_config([error]))},
|
||||||
{"invalid opt tuple", ?_assertError(badarg, parse_config([{error, true}]))}
|
{"invalid opt tuple", ?_assertError(badarg, parse_config([{error, true}]))}
|
||||||
].
|
].
|
||||||
|
@ -283,6 +309,34 @@ rep_manipulation_test_() ->
|
||||||
)}
|
)}
|
||||||
].
|
].
|
||||||
|
|
||||||
|
-ifdef(maps_support).
|
||||||
|
|
||||||
|
return_maps_test_() ->
|
||||||
|
[
|
||||||
|
{"an empty map", ?_assertEqual(
|
||||||
|
#{},
|
||||||
|
jsx:decode(<<"{}">>, [return_maps])
|
||||||
|
)},
|
||||||
|
{"an empty map", ?_assertEqual(
|
||||||
|
[{}],
|
||||||
|
jsx:decode(<<"{}">>, [])
|
||||||
|
)},
|
||||||
|
{"a small map", ?_assertEqual(
|
||||||
|
#{<<"awesome">> => true, <<"library">> => <<"jsx">>},
|
||||||
|
jsx:decode(<<"{\"library\": \"jsx\", \"awesome\": true}">>, [return_maps])
|
||||||
|
)},
|
||||||
|
{"a recursive map", ?_assertEqual(
|
||||||
|
#{<<"key">> => #{<<"key">> => true}},
|
||||||
|
jsx:decode(<<"{\"key\": {\"key\": true}}">>, [return_maps])
|
||||||
|
)},
|
||||||
|
{"a map inside a list", ?_assertEqual(
|
||||||
|
[#{}],
|
||||||
|
jsx:decode(<<"[{}]">>, [return_maps])
|
||||||
|
)}
|
||||||
|
].
|
||||||
|
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
|
||||||
handle_event_test_() ->
|
handle_event_test_() ->
|
||||||
Data = jsx:test_cases(),
|
Data = jsx:test_cases(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue