Added conditional map support for mochijson2:encode.
Project: http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/commit/5d4660df Tree: http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/tree/5d4660df Diff: http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/diff/5d4660df Branch: refs/heads/master Commit: 5d4660df8465c391304f7f760c7d04fa2f163413 Parents: 62eac24 Author: Máté Marjai <mate@theproduct.works> Authored: Sat Dec 17 20:54:21 2016 +0000 Committer: Máté Marjai <mate@theproduct.works> Committed: Sat Dec 17 20:54:21 2016 +0000 ---------------------------------------------------------------------- rebar.config | 3 ++- src/mochijson2.erl | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/blob/5d4660df/rebar.config ---------------------------------------------------------------------- diff --git a/rebar.config b/rebar.config index 59304f5..492832e 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,8 @@ {erl_opts, [debug_info, {platform_define, "R15", 'gen_tcp_r15b_workaround'}, {platform_define, "(R14|R15|R16B-)", 'crypto_compatibility'}, - {platform_define, "(R14|R15|R16B|17)", 'rand_mod_unavailable'}]}. + {platform_define, "(R14|R15|R16B|17)", 'rand_mod_unavailable'}, + {platform_define, "(17|18|19)", 'map_available'}]}. {cover_enabled, true}. {eunit_opts, [verbose, {report,{eunit_surefire,[{dir,"."}]}}]}. {dialyzer_opts, [{warnings, [no_return, http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/blob/5d4660df/src/mochijson2.erl ---------------------------------------------------------------------- diff --git a/src/mochijson2.erl b/src/mochijson2.erl index 255398d..7c63777 100644 --- a/src/mochijson2.erl +++ b/src/mochijson2.erl @@ -149,6 +149,43 @@ 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_available). +json_encode(true, _State) -> + <<"true">>; +json_encode(false, _State) -> + <<"false">>; +json_encode(null, _State) -> + <<"null">>; +json_encode(I, _State) when is_integer(I) -> + integer_to_list(I); +json_encode(F, _State) when is_float(F) -> + mochinum:digits(F); +json_encode(S, State) when is_binary(S); is_atom(S) -> + json_encode_string(S, State); +json_encode([{K, _}|_] = Props, State) when (K =/= struct andalso + K =/= array andalso + K =/= json) -> + json_encode_proplist(Props, State); +json_encode({struct, Props}, State) when is_list(Props) -> + json_encode_proplist(Props, State); +json_encode({Props}, State) when is_list(Props) -> + json_encode_proplist(Props, State); +json_encode({}, State) -> + json_encode_proplist([], State); +json_encode(Array, State) when is_list(Array) -> + json_encode_array(Array, State); +json_encode({array, Array}, State) when is_list(Array) -> + json_encode_array(Array, State); +json_encode(M, State) when is_map(M) -> + json_encode_map(M, State); +json_encode({json, IoList}, _State) -> + IoList; +json_encode(Bad, #encoder{handler=null}) -> + exit({json_encode, {bad_term, Bad}}); +json_encode(Bad, State=#encoder{handler=Handler}) -> + json_encode(Handler(Bad), State). +-else. json_encode(true, _State) -> <<"true">>; json_encode(false, _State) -> @@ -181,6 +218,7 @@ json_encode(Bad, #encoder{handler=null}) -> exit({json_encode, {bad_term, Bad}}); json_encode(Bad, State=#encoder{handler=Handler}) -> json_encode(Handler(Bad), State). +-endif. json_encode_array([], _State) -> <<"[]">>; @@ -202,6 +240,19 @@ json_encode_proplist(Props, State) -> [$, | Acc1] = lists:foldl(F, "{", Props), lists:reverse([$\} | Acc1]). +-ifdef(map_available). +json_encode_map(Map, _State) when map_size(Map) =:= 0 -> + <<"{}">>; +json_encode_map(Map, State) -> + F = fun(K, V, Acc) -> + KS = json_encode_string(K, State), + VS = json_encode(V, State), + [$,, VS, $:, KS | Acc] + end, + [$, | Acc1] = maps:fold(F, "{", Map), + lists:reverse([$\} | Acc1]). +-endif. + json_encode_string(A, State) when is_atom(A) -> json_encode_string(atom_to_binary(A, latin1), State); json_encode_string(B, State) when is_binary(B) -> @@ -939,4 +990,14 @@ utf8_non_character_test_() -> [{"roundtrip escaped", ?_assertEqual(S, decode(encode(S)))}, {"roundtrip utf8", ?_assertEqual(S, decode((encoder([{utf8, true}]))(S)))}]. +% iolist_to_binary(mochijson2:encode(#{a => 1, b => #{ c => 2}})). +-ifdef(map_available). +encode_map_test() -> + M = <<"{\"a\":1,\"b\":{\"c\":2}}">>, + ?assertEqual(M, iolist_to_binary(encode(#{a => 1, b => #{ c => 2}}))). +encode_empty_map_test() -> + ?assertEqual(<<"{}">>, encode(#{})). + +-endif. + -endif.