Browse Source

Merge pull request #22 from bkolodziej/undefined-as-null

add undefined_as_null encode option
Takeru Ohta 8 years ago
parent
commit
e67f0be961
4 changed files with 19 additions and 2 deletions
  1. 4 0
      README.md
  2. 5 1
      src/jsone.erl
  3. 5 1
      src/jsone_encode.erl
  4. 5 0
      test/jsone_encode_tests.erl

+ 4 - 0
README.md

@@ -124,6 +124,10 @@ Usage Example
 > jsone:encode({[{123, <<"value">>}]}, [{object_key_type, scalar}]).
 <<"{\"123\":\"value\"}">>
 
+% 'undefined_as_null' option allows encoding atom undefined as null
+> jsone:encode(undefined,[undefined_as_null]).
+<<"null">>
+
 %% Pretty Print
 > Data = [true, #{<<"1">> => 2, <<"array">> => [[[[1]]], #{<<"ab">> => <<"cd">>}, false]}, null].
 > io:format("~s\n", [jsone:encode(Data, [{indent, 1}, {space, 2}])]).

+ 5 - 1
src/jsone.erl

@@ -189,7 +189,8 @@
                        | {datetime_format, datetime_encode_format()}
                        | {object_key_type, string | scalar | value}
                        | {space, non_neg_integer()}
-                       | {indent, non_neg_integer()}.
+                       | {indent, non_neg_integer()}
+                       | undefined_as_null.
 %% `native_utf8': <br />
 %% - Encodes UTF-8 characters as a human-readable(non-escaped) string <br />
 %%
@@ -219,6 +220,9 @@
 %% `{indent, N}': <br />
 %% - Inserts a newline and `N' spaces for each level of indentation <br />
 %% - default: `0' <br />
+%%
+%% `undefined_as_null': <br />
+%% - Encodes atom `undefined` as null value <br />
 
 -type decode_option() :: {object_format, tuple | proplist | map}
                        | {allow_ctrl_chars, boolean()}

+ 5 - 1
src/jsone_encode.erl

@@ -68,7 +68,8 @@
           datetime_format = {iso8601, 0} :: {jsone:datetime_format(), jsone:utc_offset_seconds()},
           object_key_type = string :: string | scalar | value,
           space = 0 :: non_neg_integer(),
-          indent = 0 :: non_neg_integer()
+          indent = 0 :: non_neg_integer(),
+          undefined_as_null = false :: boolean()
          }).
 -define(OPT, #encode_opt_v2).
 -type opt() :: #encode_opt_v2{}.
@@ -110,6 +111,7 @@ next(Level = [Next | Nexts], Buf, Opt) ->
 
 -spec value(jsone:json_value(), [next()], binary(), opt()) -> encode_result().
 value(null, Nexts, Buf, Opt)                         -> next(Nexts, <<Buf/binary, "null">>, Opt);
+value(undefined, Nexts, Buf, Opt = ?OPT{undefined_as_null = true}) -> next(Nexts, <<Buf/binary, "null">>, Opt);
 value(false, Nexts, Buf, Opt)                        -> next(Nexts, <<Buf/binary, "false">>, Opt);
 value(true, Nexts, Buf, Opt)                         -> next(Nexts, <<Buf/binary, "true">>, Opt);
 value({{json, T}}, Nexts, Buf, Opt) ->
@@ -373,6 +375,8 @@ parse_option([{datetime_format, Fmt}|T], Opt) ->
         {iso8601, N} when -86400 < N, N < 86400 -> parse_option(T, Opt?OPT{datetime_format = {iso8601, N}});
         _                                       -> error(badarg, [[{datetime_format, Fmt}|T], Opt])
     end;
+parse_option([undefined_as_null|T],Opt) ->
+    parse_option(T, Opt?OPT{undefined_as_null = true});
 parse_option(List, Opt) ->
     error(badarg, [List, Opt]).
 

+ 5 - 0
test/jsone_encode_tests.erl

@@ -242,6 +242,11 @@ encode_test_() ->
               ?assertMatch({error, {badarg, _}}, jsone_encode:encode({[{1, 2}]})),
               ?assertMatch({error, {badarg, _}}, jsone_encode:encode({[{"1", 2}]}))
       end},
+     {"undefined_as_null option",
+      fun() ->
+              ?assertEqual({ok,<<"null">>},          jsone_encode:encode(undefined,[undefined_as_null])), % OK
+              ?assertEqual({ok,<<"\"undefined\"">>}, jsone_encode:encode(undefined,[])) % OK
+      end},
 
      %% Pretty Print
      {"space",