Skip to content
Permalink
Browse files
add map support for mochijson2:decode/2
Option {format, map} switch output to map.
  • Loading branch information
lego12239 committed Dec 3, 2018
1 parent 9608d78 commit 2d734a9cbb3c4aad3159d0d54a3af998f129ffee
Showing 1 changed file with 19 additions and 2 deletions.
@@ -125,10 +125,11 @@ decoder(Options) ->
State = parse_decoder_options(Options, #decoder{}),
fun (O) -> json_decode(O, State) end.

%% @spec decode(iolist(), [{format, proplist | eep18 | struct}]) -> json_term()
%% @spec decode(iolist(), [{format, proplist | eep18 | struct | map}]) -> json_term()
%% @doc Decode the given iolist to Erlang terms using the given object format
%% for decoding, where proplist returns JSON objects as [{binary(), json_term()}]
%% proplists, eep18 returns JSON objects as {[binary(), json_term()]}, and struct
%% proplists, eep18 returns JSON objects as {[binary(), json_term()]},
%% map returns JSON objects as #{binary() => json_term()}, and struct
%% returns them as-is.
decode(S, Options) ->
json_decode(S, parse_decoder_options(Options, #decoder{})).
@@ -151,10 +152,21 @@ parse_decoder_options([], State) ->
State;
parse_decoder_options([{object_hook, Hook} | Rest], State) ->
parse_decoder_options(Rest, State#decoder{object_hook=Hook});
parse_decoder_options([{format, map} | Rest], State) ->
Hook = make_object_hook_for_map(),
parse_decoder_options(Rest, State#decoder{object_hook=Hook});
parse_decoder_options([{format, Format} | Rest], State)
when Format =:= struct orelse Format =:= eep18 orelse Format =:= proplist ->
parse_decoder_options(Rest, State#decoder{object_hook=Format}).

-ifdef(map_unavailable).
make_object_hook_for_map() ->
exit({json_decode, {bad_format, map_unavailable}}).
-else.
make_object_hook_for_map() ->
fun ({struct, P}) -> maps:from_list(P) end.
-endif.


json_encode(true, _State) ->
<<"true">>;
@@ -967,6 +979,11 @@ utf8_non_character_test_() ->

-ifndef(map_unavailable).

decode_map_test() ->
Json = "{\"var1\": 3, \"var2\": {\"var3\": 7}}",
M = #{<<"var1">> => 3,<<"var2">> => #{<<"var3">> => 7}},
?assertEqual(M, decode(Json, [{format, map}])).

encode_map_test() ->
M = <<"{\"a\":1,\"b\":{\"c\":2}}">>,
?assertEqual(M, iolist_to_binary(encode(#{a => 1, b => #{ c => 2}}))).

0 comments on commit 2d734a9

Please sign in to comment.