semantic change to way pre_encode works

This commit is contained in:
alisdair sullivan 2012-04-06 08:09:52 -07:00
parent 5e87f02fc5
commit 76723ce736
4 changed files with 22 additions and 40 deletions

View file

@ -147,11 +147,11 @@ this option treats all exhausted inputs as incomplete, as explained below. the p
relax is a synonym for `[replaced_bad_utf8, single_quoted_strings, comments, ignored_bad_escapes]` for when you don't care how janky and awful your json input is, you just want the parser to do the best it can
#### `{pre_encoder, F}` or `{pre_encoders, [F, G,...]}` ####
#### `{pre_encode, F}` ####
pre encoders are functions of arity 1 that pre-process input to the encoder. only input evaluated in a *value* context is pre-processed in this manner (so keys are not pre-processed, but objects and lists are). if more than one pre encoder is declared, the input will be passed to each of them in the order they are declared
`F` is a function of arity 1 that pre-process input to the encoder. only input evaluated in a *value* context is pre-processed in this manner (so keys are not pre-processed, but objects and arrays are). if more than one pre encoder is declared, a `badarg` exception will occur
input can be any term, but final output from the chain should be otherwise recognized input to the encoder
input can be any term, but output from the function must be a valid type for input
### <a name="incompletes">incomplete input</a> ###

View file

@ -99,7 +99,8 @@ list([], {Handler, State}, _Opts) -> Handler:handle_event(end_array, State);
list(Term, Handler, Opts) -> ?error([Term, Handler, Opts]).
pre_encode(Value, Opts) -> lists:foldl(fun(F, V) -> F(V) end, Value, Opts#opts.pre_encoders).
pre_encode(Value, #opts{pre_encode=false}) -> Value;
pre_encode(Value, Opts) -> (Opts#opts.pre_encode)(Value).
fix_key(Key) when is_atom(Key) -> fix_key(atom_to_binary(Key, utf8));
@ -812,7 +813,7 @@ pre_encoders_test_() ->
]
)},
{"replace lists with empty lists", ?_assertEqual(
encode(Term, [{pre_encoder, fun(V) -> case V of [{_,_}|_] -> V; [{}] -> V; V when is_list(V) -> []; _ -> V end end}]),
encode(Term, [{pre_encode, fun(V) -> case V of [{_,_}|_] -> V; [{}] -> V; V when is_list(V) -> []; _ -> V end end}]),
[
start_object,
{key, <<"object">>}, start_object,
@ -825,7 +826,7 @@ pre_encoders_test_() ->
]
)},
{"replace objects with empty objects", ?_assertEqual(
encode(Term, [{pre_encoder, fun(V) -> case V of [{_,_}|_] -> [{}]; _ -> V end end}]),
encode(Term, [{pre_encode, fun(V) -> case V of [{_,_}|_] -> [{}]; _ -> V end end}]),
[
start_object,
end_object,
@ -833,7 +834,7 @@ pre_encoders_test_() ->
]
)},
{"replace all non-list values with false", ?_assertEqual(
encode(Term, [{pre_encoder, fun(V) when is_list(V) -> V; (_) -> false end}]),
encode(Term, [{pre_encode, fun(V) when is_list(V) -> V; (_) -> false end}]),
[
start_object,
{key, <<"object">>}, start_object,
@ -852,7 +853,7 @@ pre_encoders_test_() ->
]
)},
{"replace all atoms with atom_to_list", ?_assertEqual(
encode(Term, [{pre_encoder, fun(V) when is_atom(V) -> unicode:characters_to_binary(atom_to_list(V)); (V) -> V end}]),
encode(Term, [{pre_encode, fun(V) when is_atom(V) -> unicode:characters_to_binary(atom_to_list(V)); (V) -> V end}]),
[
start_object,
{key, <<"object">>}, start_object,
@ -869,28 +870,6 @@ pre_encoders_test_() ->
end_object,
end_json
]
)},
{"replace all atoms to strings and back", ?_assertEqual(
encode(Term, [{pre_encoders, [
fun(V) when is_atom(V) -> unicode:characters_to_binary(atom_to_list(V)); (V) -> V end,
fun(<<"true">>) -> true; (<<"false">>) -> false; (<<"null">>) -> null; (V) -> V end
]}]),
[
start_object,
{key, <<"object">>}, start_object,
{key, <<"literals">>}, start_array,
{literal, true}, {literal, false}, {literal, null},
end_array,
{key, <<"strings">>}, start_array,
{string, <<"foo">>}, {string, <<"bar">>}, {string, <<"baz">>},
end_array,
{key, <<"numbers">>}, start_array,
{integer, 1}, {float, 1.0}, {float, 1.0},
end_array,
end_object,
end_object,
end_json
]
)}
].

View file

@ -8,5 +8,5 @@
dirty_strings = false,
ignored_bad_escapes = false,
explicit_end = false,
pre_encoders = []
pre_encode = false
}).

View file

@ -61,14 +61,17 @@ parse_opts([relax|Rest], Opts) ->
comments = true,
ignored_bad_escapes = true
});
parse_opts([{pre_encoder, Encoder}|Rest], Opts) when is_function(Encoder, 1) ->
AllEncoders = Opts#opts.pre_encoders ++ [Encoder],
parse_opts(Rest, Opts#opts{pre_encoders=AllEncoders});
parse_opts([{pre_encoders, Encoders}|Rest], Opts) when is_list(Encoders) ->
lists:foreach(fun(F) when is_function(F, 1) -> ok end, Encoders),
AllEncoders = Opts#opts.pre_encoders ++ Encoders,
parse_opts(Rest, Opts#opts{pre_encoders=AllEncoders});
parse_opts([{pre_encode, Encoder}|Rest] = Options, Opts) when is_function(Encoder, 1) ->
case Opts#opts.pre_encode of
false -> parse_opts(Rest, Opts#opts{pre_encode=Encoder})
; _ -> erlang:error(badarg, [Options, Opts])
end;
%% deprecated flags
parse_opts([{pre_encoder, Encoder}|Rest] = Options, Opts) when is_function(Encoder, 1) ->
case Opts#opts.pre_encode of
false -> parse_opts(Rest, Opts#opts{pre_encode=Encoder})
; _ -> erlang:error(badarg, [Options, Opts])
end;
parse_opts([loose_unicode|Rest], Opts) ->
parse_opts(Rest, Opts#opts{replaced_bad_utf8=true});
parse_opts([escape_forward_slash|Rest], Opts) ->
@ -97,9 +100,9 @@ valid_flags() ->
ignored_bad_escapes,
explicit_end,
relax,
pre_encoder,
pre_encoders,
pre_encode,
%% deprecated flags
pre_encoder, %% pre_encode
loose_unicode, %% replaced_bad_utf8
escape_forward_slash, %% escaped_forward_slashes
single_quotes, %% single_quotes_strings