Closed ghost closed 3 years ago
Merging #49 into master will increase coverage by
0.61%
. The diff coverage is100.00%
.
@@ Coverage Diff @@
## master #49 +/- ##
==========================================
+ Coverage 88.72% 89.34% +0.61%
==========================================
Files 3 3
Lines 275 291 +16
==========================================
+ Hits 244 260 +16
Misses 31 31
Impacted Files | Coverage Δ | |
---|---|---|
src/jsone_encode.erl | 87.01% <100.00%> (+1.50%) |
:arrow_up: |
Continue to review full report at Codecov.
Legend - Click here to learn more
Δ = absolute <relative> (impact)
,ø = not affected
,? = missing data
Powered by Codecov. Last update 2ebbe23...558b08c. Read the comment docs.
Thank you for your PR but I'm wondering how many users want this feature. If this is a feature specific to your need, I'd like to implement a more generic feature, like map_unknown_value
option below, instead and enable encoding IP addresses by using it.
diff --git a/src/jsone.erl b/src/jsone.erl
index 11878ec..2f2e40d 100644
--- a/src/jsone.erl
+++ b/src/jsone.erl
@@ -196,6 +196,7 @@
| {object_key_type, string | scalar | value}
| {space, non_neg_integer()}
| {indent, non_neg_integer()}
+ | {map_unknown_value, fun ((term()) -> {ok, json_value()} | error)}
| common_option().
%% `native_utf8': <br />
%% - Encodes non ASCII UTF-8 characters as a human-readable(non-escaped) string <br />
diff --git a/src/jsone_encode.erl b/src/jsone_encode.erl
index 6cdf98a..4ce79be 100644
--- a/src/jsone_encode.erl
+++ b/src/jsone_encode.erl
@@ -70,7 +70,8 @@
object_key_type = string :: string | scalar | value,
space = 0 :: non_neg_integer(),
indent = 0 :: non_neg_integer(),
- undefined_as_null = false :: boolean()
+ undefined_as_null = false :: boolean(),
+ map_unknown_value = undefined :: undefined | fun ((term()) -> {ok, jsone:json_value()} | error)
}).
-define(OPT, #encode_opt_v2).
-type opt() :: #encode_opt_v2{}.
@@ -142,7 +143,15 @@ value([{{_,_,_},{_,_,_}}|_] = Value, Nexts, Buf, Opt)-> array(Value, Nexts, Buf,
value([{_, _}|_] = Value, Nexts, Buf, Opt) -> object(Value, Nexts, Buf, Opt);
value(Value, Nexts, Buf, Opt) when ?IS_MAP(Value) -> ?ENCODE_MAP(Value, Nexts, Buf, Opt);
value(Value, Nexts, Buf, Opt) when is_list(Value) -> array(Value, Nexts, Buf, Opt);
-value(Value, Nexts, Buf, Opt) -> ?ERROR(value, [Value, Nexts, Buf, Opt]).
+value(Value, Nexts, Buf, Opt) ->
+ case Opt?OPT.map_unknown_value of
+ undefined -> ?ERROR(value, [Value, Nexts, Buf, Opt]);
+ Fun ->
+ case Fun(Value) of
+ error -> ?ERROR(value, [Value, Nexts, Buf, Opt]);
+ {ok, Value1} -> value(Value1, Nexts, Buf, Opt)
+ end
+ end.
-spec string(jsone:json_string(), [next()], binary(), opt()) -> encode_result().
string(<<Str/binary>>, Nexts, Buf, Opt) ->
@@ -385,6 +394,8 @@ parse_option([{datetime_format, Fmt}|T], Opt) ->
end;
parse_option([undefined_as_null|T],Opt) ->
parse_option(T, Opt?OPT{undefined_as_null = true});
+parse_option([{map_known_value, Fun}|T], Opt) when is_function(Fun) ->
+ parse_option(T, Opt?OPT{map_value=Fun});
parse_option(List, Opt) ->
error(badarg, [List, Opt]).
> jsone:encode([{1,2,3,4}], [{map_value, fun ({_,_,_,_} = Ip4) -> {ok, list_to_binary(inet:ntoa(Ip4))} end}]).
<<"[\"1,2,3,4\"]">>
What do you think of it?
Another possibility would be to use {Type, Value}
tuples, e.g. {ipv4_address, {192, 168, 0, 1}}
. In general, relying on the shape of tuples to infer the type of data they represent can cause interesting issues. But I like the function proposed by @sile, it would be nice to be able to support various kind of data types without having to patch jsone.
@galdor Thank you for your comment! I'll create a PR to add the map_value
feature in the near future.
Let me close this PR since I implemented the map_unknown_value
option described above in #51.
This change supports encoding ip addresses and CIDR values into json. I added these changes to allow encoding postgres database's
inet
/cidr
column values into json.