Skip to content

Commit

Permalink
semantic change to way pre_encode works
Browse files Browse the repository at this point in the history
  • Loading branch information
alisdair sullivan committed Apr 6, 2012
1 parent 5e87f02 commit 76723ce
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 40 deletions.
6 changes: 3 additions & 3 deletions README.markdown
Expand Up @@ -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> ###
Expand Down
33 changes: 6 additions & 27 deletions src/jsx_encoder.erl
Expand Up @@ -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));
Expand Down Expand Up @@ -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,
Expand All @@ -825,15 +826,15 @@ 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,
end_json
]
)},
{"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,
Expand All @@ -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,
Expand All @@ -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
]
)}
].

Expand Down
2 changes: 1 addition & 1 deletion src/jsx_opts.hrl
Expand Up @@ -8,5 +8,5 @@
dirty_strings = false,
ignored_bad_escapes = false,
explicit_end = false,
pre_encoders = []
pre_encode = false
}).
21 changes: 12 additions & 9 deletions src/jsx_utils.erl
Expand Up @@ -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) ->
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 76723ce

Please sign in to comment.