Add sloppy_existing_atom as a configuration option for labels

This commit is contained in:
John Daily 2013-07-03 21:51:26 -04:00
parent 352d6b21cb
commit 1da0c567ba
2 changed files with 28 additions and 8 deletions

View file

@ -467,18 +467,20 @@ decode(JSON, Opts) -> Term
JSON = json_text() JSON = json_text()
Term = json_term() Term = json_term()
Opts = [option() | labels | {labels, Label} | {post_decode, F}] Opts = [option() | labels | {labels, Label} | {post_decode, F}]
Label = binary | atom | existing_atom Label = binary | atom | existing_atom | sloppy_existing_atom
F = fun((any()) -> any()) F = fun((any()) -> any())
``` ```
`decode` parses a json text (a `utf8` encoded binary) and produces an erlang `decode` parses a json text (a `utf8` encoded binary) and produces an erlang
term term
the option `labels` controls how keys are converted from json to erlang terms. the option `labels` controls how keys are converted from json to
`binary` does no conversion beyond normal escaping. `atom` converts keys to erlang terms. `binary` (the default behavior) does no conversion
erlang atoms and results in a badarg error if the keys fall outside the range of beyond normal escaping. `atom` converts keys to erlang atoms and
erlang atoms. `existing_atom` is identical to `atom` except it will not add new results in a badarg error if the keys fall outside the range of erlang
atoms to the atom table atoms. `existing_atom` is identical to `atom` except it will not add
new atoms to the atom table. `sloppy_existing_atom` will convert keys
to atoms when they exist, and leave them as binary otherwise
`{post_decode, F}` is a user defined function of arity 1 that is called on each `{post_decode, F}` is a user defined function of arity 1 that is called on each
output value (objects, arrays, strings, numbers and literals). it may return any output value (objects, arrays, strings, numbers and literals). it may return any

View file

@ -53,7 +53,7 @@ to_term(Source, Config) when is_list(Config) ->
parse_config(Config) -> parse_config(Config, #config{}). parse_config(Config) -> parse_config(Config, #config{}).
parse_config([{labels, Val}|Rest], Config) parse_config([{labels, Val}|Rest], Config)
when Val == binary; Val == atom; Val == existing_atom -> when Val == binary; Val == atom; Val == existing_atom; Val == sloppy_existing_atom ->
parse_config(Rest, Config#config{labels = Val}); parse_config(Rest, Config#config{labels = Val});
parse_config([labels|Rest], Config) -> parse_config([labels|Rest], Config) ->
parse_config(Rest, Config#config{labels = binary}); parse_config(Rest, Config#config{labels = binary});
@ -107,6 +107,12 @@ format_key(Key, Config) ->
binary -> Key binary -> Key
; atom -> binary_to_atom(Key, utf8) ; atom -> binary_to_atom(Key, utf8)
; existing_atom -> binary_to_existing_atom(Key, utf8) ; existing_atom -> binary_to_existing_atom(Key, utf8)
; sloppy_existing_atom ->
try binary_to_existing_atom(Key, utf8) of
Result -> Result
catch
error:badarg -> Key
end
end. end.
@ -133,6 +139,10 @@ config_test_() ->
#config{labels=existing_atom}, #config{labels=existing_atom},
parse_config([{labels, existing_atom}]) parse_config([{labels, existing_atom}])
)}, )},
{"sloppy existing atom labels", ?_assertEqual(
#config{labels=sloppy_existing_atom},
parse_config([{labels, sloppy_existing_atom}])
)},
{"post decode", ?_assertEqual( {"post decode", ?_assertEqual(
#config{post_decode=F}, #config{post_decode=F},
parse_config([{post_decode, F}]) parse_config([{post_decode, F}])
@ -154,6 +164,14 @@ format_key_test_() ->
{"nonexisting atom key", ?_assertError( {"nonexisting atom key", ?_assertError(
badarg, badarg,
format_key(<<"nonexistentatom">>, #config{labels=existing_atom}) format_key(<<"nonexistentatom">>, #config{labels=existing_atom})
)},
{"sloppy existing atom key", ?_assertEqual(
key,
format_key(<<"key">>, #config{labels=sloppy_existing_atom})
)},
{"nonexisting atom key", ?_assertEqual(
<<"nonexistentatom">>,
format_key(<<"nonexistentatom">>, #config{labels=sloppy_existing_atom})
)} )}
]. ].