Browse files

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

…tion
  • Loading branch information...
1 parent cfc3af6 commit 497f1fc02f513a4d6488820025384e0dcf8fa7ab @etrepum etrepum committed Aug 30, 2011
Showing with 52 additions and 10 deletions.
  1. +51 −9 src/mochijson2.erl
  2. +1 −1 src/mochiweb.app.src
View
60 src/mochijson2.erl
@@ -40,9 +40,9 @@
-module(mochijson2).
-author('bob@mochimedia.com').
-export([encoder/1, encode/1]).
--export([decoder/1, decode/1]).
+-export([decoder/1, decode/1, decode/2]).
-% This is a macro to placate syntax highlighters..
+%% This is a macro to placate syntax highlighters..
-define(Q, $\").
-define(ADV_COL(S, N), S#decoder{offset=N+S#decoder.offset,
column=N+S#decoder.column}).
@@ -70,9 +70,10 @@
%% @type json_number() = integer() | float()
%% @type json_array() = [json_term()]
%% @type json_object() = {struct, [{json_string(), json_term()}]}
+%% @type json_eep18_object() = {[{json_string(), json_term()}]}
%% @type json_iolist() = {json, iolist()}
%% @type json_term() = json_string() | json_number() | json_array() |
-%% json_object() | json_iolist()
+%% json_object() | json_eep18_object() | json_iolist()
-record(encoder, {handler=null,
utf8=false}).
@@ -102,6 +103,14 @@ decoder(Options) ->
State = parse_decoder_options(Options, #decoder{}),
fun (O) -> json_decode(O, State) end.
+%% @spec decode(iolist(), [{format, proplist | eep18 | struct}]) -> 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
+%% returns them as-is.
+decode(S, Options) ->
+ json_decode(S, parse_decoder_options(Options, #decoder{})).
+
%% @spec decode(iolist()) -> json_term()
%% @doc Decode the given iolist to Erlang terms.
decode(S) ->
@@ -119,7 +128,10 @@ parse_encoder_options([{utf8, Switch} | Rest], State) ->
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(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}).
json_encode(true, _State) ->
<<"true">>;
@@ -139,6 +151,10 @@ json_encode([{K, _}|_] = Props, State) when (K =/= struct andalso
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) ->
@@ -318,8 +334,12 @@ decode1(B, S=#decoder{state=null}) ->
decode_object(B, S1)
end.
-make_object(V, #decoder{object_hook=null}) ->
+make_object(V, #decoder{object_hook=N}) when N =:= null orelse N =:= struct ->
V;
+make_object({struct, P}, #decoder{object_hook=eep18}) ->
+ {P};
+make_object({struct, P}, #decoder{object_hook=proplist}) ->
+ P;
make_object(V, #decoder{object_hook=Hook}) ->
Hook(V).
@@ -838,12 +858,34 @@ float_test() ->
handler_test() ->
?assertEqual(
- {'EXIT',{json_encode,{bad_term,{}}}},
- catch encode({})),
- F = fun ({}) -> [] end,
+ {'EXIT',{json_encode,{bad_term,{x,y}}}},
+ catch encode({x,y})),
+ F = fun ({x,y}) -> [] end,
?assertEqual(
<<"[]">>,
- iolist_to_binary((encoder([{handler, F}]))({}))),
+ iolist_to_binary((encoder([{handler, F}]))({x, y}))),
ok.
+encode_empty_test_() ->
+ [{A, ?_assertEqual(<<"{}">>, iolist_to_binary(encode(B)))}
+ || {A, B} <- [{"eep18 {}", {}},
+ {"eep18 {[]}", {[]}},
+ {"{struct, []}", {struct, []}}]].
+
+encode_test_() ->
+ P = [{<<"k">>, <<"v">>}],
+ JSON = iolist_to_binary(encode({struct, P})),
+ [{atom_to_list(F),
+ ?_assertEqual(JSON, iolist_to_binary(encode(decode(JSON, [{format, F}]))))}
+ || F <- [struct, eep18, proplist]].
+
+format_test_() ->
+ P = [{<<"k">>, <<"v">>}],
+ JSON = iolist_to_binary(encode({struct, P})),
+ [{atom_to_list(F),
+ ?_assertEqual(A, decode(JSON, [{format, F}]))}
+ || {F, A} <- [{struct, {struct, P}},
+ {eep18, {P}},
+ {proplist, P}]].
+
-endif.
View
2 src/mochiweb.app.src
@@ -1,7 +1,7 @@
%% This is generated from src/mochiweb.app.src
{application, mochiweb,
[{description, "MochiMedia Web Server"},
- {vsn, "2.0.0"},
+ {vsn, "2.1.0"},
{modules, []},
{registered, []},
{env, []},

0 comments on commit 497f1fc

Please sign in to comment.