Skip to content
This repository
Browse code

add mochijson2:decode/2 with [{format, eep18 | proplist | struct}] op…

…tion
  • Loading branch information...
commit 497f1fc02f513a4d6488820025384e0dcf8fa7ab 1 parent cfc3af6
Bob Ippolito etrepum authored

Showing 2 changed files with 52 additions and 10 deletions. Show diff stats Hide diff stats

  1. +51 9 src/mochijson2.erl
  2. +1 1  src/mochiweb.app.src
60 src/mochijson2.erl
@@ -40,9 +40,9 @@
40 40 -module(mochijson2).
41 41 -author('bob@mochimedia.com').
42 42 -export([encoder/1, encode/1]).
43   --export([decoder/1, decode/1]).
  43 +-export([decoder/1, decode/1, decode/2]).
44 44
45   -% This is a macro to placate syntax highlighters..
  45 +%% This is a macro to placate syntax highlighters..
46 46 -define(Q, $\").
47 47 -define(ADV_COL(S, N), S#decoder{offset=N+S#decoder.offset,
48 48 column=N+S#decoder.column}).
@@ -70,9 +70,10 @@
70 70 %% @type json_number() = integer() | float()
71 71 %% @type json_array() = [json_term()]
72 72 %% @type json_object() = {struct, [{json_string(), json_term()}]}
  73 +%% @type json_eep18_object() = {[{json_string(), json_term()}]}
73 74 %% @type json_iolist() = {json, iolist()}
74 75 %% @type json_term() = json_string() | json_number() | json_array() |
75   -%% json_object() | json_iolist()
  76 +%% json_object() | json_eep18_object() | json_iolist()
76 77
77 78 -record(encoder, {handler=null,
78 79 utf8=false}).
@@ -102,6 +103,14 @@ decoder(Options) ->
102 103 State = parse_decoder_options(Options, #decoder{}),
103 104 fun (O) -> json_decode(O, State) end.
104 105
  106 +%% @spec decode(iolist(), [{format, proplist | eep18 | struct}]) -> json_term()
  107 +%% @doc Decode the given iolist to Erlang terms using the given object format
  108 +%% for decoding, where proplist returns JSON objects as [{binary(), json_term()}]
  109 +%% proplists, eep18 returns JSON objects as {[binary(), json_term()]}, and struct
  110 +%% returns them as-is.
  111 +decode(S, Options) ->
  112 + json_decode(S, parse_decoder_options(Options, #decoder{})).
  113 +
105 114 %% @spec decode(iolist()) -> json_term()
106 115 %% @doc Decode the given iolist to Erlang terms.
107 116 decode(S) ->
@@ -119,7 +128,10 @@ parse_encoder_options([{utf8, Switch} | Rest], State) ->
119 128 parse_decoder_options([], State) ->
120 129 State;
121 130 parse_decoder_options([{object_hook, Hook} | Rest], State) ->
122   - parse_decoder_options(Rest, State#decoder{object_hook=Hook}).
  131 + parse_decoder_options(Rest, State#decoder{object_hook=Hook});
  132 +parse_decoder_options([{format, Format} | Rest], State)
  133 + when Format =:= struct orelse Format =:= eep18 orelse Format =:= proplist ->
  134 + parse_decoder_options(Rest, State#decoder{object_hook=Format}).
123 135
124 136 json_encode(true, _State) ->
125 137 <<"true">>;
@@ -139,6 +151,10 @@ json_encode([{K, _}|_] = Props, State) when (K =/= struct andalso
139 151 json_encode_proplist(Props, State);
140 152 json_encode({struct, Props}, State) when is_list(Props) ->
141 153 json_encode_proplist(Props, State);
  154 +json_encode({Props}, State) when is_list(Props) ->
  155 + json_encode_proplist(Props, State);
  156 +json_encode({}, State) ->
  157 + json_encode_proplist([], State);
142 158 json_encode(Array, State) when is_list(Array) ->
143 159 json_encode_array(Array, State);
144 160 json_encode({array, Array}, State) when is_list(Array) ->
@@ -318,8 +334,12 @@ decode1(B, S=#decoder{state=null}) ->
318 334 decode_object(B, S1)
319 335 end.
320 336
321   -make_object(V, #decoder{object_hook=null}) ->
  337 +make_object(V, #decoder{object_hook=N}) when N =:= null orelse N =:= struct ->
322 338 V;
  339 +make_object({struct, P}, #decoder{object_hook=eep18}) ->
  340 + {P};
  341 +make_object({struct, P}, #decoder{object_hook=proplist}) ->
  342 + P;
323 343 make_object(V, #decoder{object_hook=Hook}) ->
324 344 Hook(V).
325 345
@@ -838,12 +858,34 @@ float_test() ->
838 858
839 859 handler_test() ->
840 860 ?assertEqual(
841   - {'EXIT',{json_encode,{bad_term,{}}}},
842   - catch encode({})),
843   - F = fun ({}) -> [] end,
  861 + {'EXIT',{json_encode,{bad_term,{x,y}}}},
  862 + catch encode({x,y})),
  863 + F = fun ({x,y}) -> [] end,
844 864 ?assertEqual(
845 865 <<"[]">>,
846   - iolist_to_binary((encoder([{handler, F}]))({}))),
  866 + iolist_to_binary((encoder([{handler, F}]))({x, y}))),
847 867 ok.
848 868
  869 +encode_empty_test_() ->
  870 + [{A, ?_assertEqual(<<"{}">>, iolist_to_binary(encode(B)))}
  871 + || {A, B} <- [{"eep18 {}", {}},
  872 + {"eep18 {[]}", {[]}},
  873 + {"{struct, []}", {struct, []}}]].
  874 +
  875 +encode_test_() ->
  876 + P = [{<<"k">>, <<"v">>}],
  877 + JSON = iolist_to_binary(encode({struct, P})),
  878 + [{atom_to_list(F),
  879 + ?_assertEqual(JSON, iolist_to_binary(encode(decode(JSON, [{format, F}]))))}
  880 + || F <- [struct, eep18, proplist]].
  881 +
  882 +format_test_() ->
  883 + P = [{<<"k">>, <<"v">>}],
  884 + JSON = iolist_to_binary(encode({struct, P})),
  885 + [{atom_to_list(F),
  886 + ?_assertEqual(A, decode(JSON, [{format, F}]))}
  887 + || {F, A} <- [{struct, {struct, P}},
  888 + {eep18, {P}},
  889 + {proplist, P}]].
  890 +
849 891 -endif.
2  src/mochiweb.app.src
... ... @@ -1,7 +1,7 @@
1 1 %% This is generated from src/mochiweb.app.src
2 2 {application, mochiweb,
3 3 [{description, "MochiMedia Web Server"},
4   - {vsn, "2.0.0"},
  4 + {vsn, "2.1.0"},
5 5 {modules, []},
6 6 {registered, []},
7 7 {env, []},

0 comments on commit 497f1fc

Please sign in to comment.
Something went wrong with that request. Please try again.