Просмотр исходного кода

fix(json): fix decoding/encoding empty object error

JianBo He 5 лет назад
Родитель
Сommit
b373c0cf1b
3 измененных файлов с 40 добавлено и 14 удалено
  1. 10 3
      src/emqx.appup.src
  2. 4 1
      src/emqx_json.erl
  3. 26 10
      test/emqx_json_SUITE.erl

+ 10 - 3
src/emqx.appup.src

@@ -1,3 +1,4 @@
+%% -*-: erlang -*-
 {DefaultLen, DefaultSize} =
     case WordSize = erlang:system_info(wordsize) of
         8 -> % arch_64
@@ -9,10 +10,13 @@
   [
     {"4.2.1", [
       {load_module, emqx_channel, brutal_purge, soft_purge, []},
-      {load_module, emqx_mod_topic_metrics, brutal_purge, soft_purge, []}
+      {load_module, emqx_mod_topic_metrics, brutal_purge, soft_purge, []},
+      {load_module, emqx_json, brutal_purge, soft_purge, []}
     ]},
     {"4.2.0", [
       {load_module, emqx_channel, brutal_purge, soft_purge, []},
+      {load_module, emqx_mod_topic_metrics, brutal_purge, soft_purge, []},
+      {load_module, emqx_json, brutal_purge, soft_purge, []},
       {apply, {application, set_env,
                 [emqx, force_shutdown_policy,
                  #{message_queue_len => DefaultLen,
@@ -22,10 +26,13 @@
   [
     {"4.2.1", [
       {load_module, emqx_channel, brutal_purge, soft_purge, []},
-      {load_module, emqx_mod_topic_metrics, brutal_purge, soft_purge, []}
+      {load_module, emqx_mod_topic_metrics, brutal_purge, soft_purge, []},
+      {load_module, emqx_json, brutal_purge, soft_purge, []}
     ]},
     {"4.2.0", [
-      {load_module, emqx_channel, brutal_purge, soft_purge, []}
+      {load_module, emqx_channel, brutal_purge, soft_purge, []},
+      {load_module, emqx_mod_topic_metrics, brutal_purge, soft_purge, []},
+      {load_module, emqx_json, brutal_purge, soft_purge, []}
     ]}
   ]
 }.

+ 4 - 1
src/emqx_json.erl

@@ -103,6 +103,8 @@ safe_decode(Json, Opts) ->
           , from_ejson/1
           ]}).
 
+to_ejson([{}]) ->
+    {[]};
 to_ejson([{_, _}|_] = L) ->
     {[{K, to_ejson(V)} || {K, V} <- L ]};
 to_ejson(L) when is_list(L) ->
@@ -111,6 +113,8 @@ to_ejson(T) -> T.
 
 from_ejson(L) when is_list(L) ->
     [from_ejson(E) || E <- L];
+from_ejson({[]}) ->
+    [{}];
 from_ejson({L}) ->
     [{Name, from_ejson(Value)} || {Name, Value} <- L];
 from_ejson(T) -> T.
@@ -118,4 +122,3 @@ from_ejson(T) -> T.
 to_binary(B) when is_binary(B) -> B;
 to_binary(L) when is_list(L) ->
     iolist_to_binary(L).
-

+ 26 - 10
test/emqx_json_SUITE.erl

@@ -27,6 +27,7 @@
         , decode/2
         ]).
 
+%% copied jiffy/readme
 %%--------------------------------------------------------------------
 %% Erlang                     JSON              Erlang
 %% -------------------------------------------------------------------
@@ -45,10 +46,27 @@
 %% {[{foo, bar}]}             -> {"foo": "bar"} -> {[{<<"foo">>, <<"bar">>}]}
 %% {[{<<"foo">>, <<"bar">>}]} -> {"foo": "bar"} -> {[{<<"foo">>, <<"bar">>}]}
 %% #{<<"foo">> => <<"bar">>}  -> {"foo": "bar"} -> #{<<"foo">> => <<"bar">>}
+%%--------------------------------------------------------------------
+
+%% but in emqx_json, we use the jsx style for it:
+%%--------------------------------------------------------------------
+%% Erlang                     JSON              Erlang
+%% -------------------------------------------------------------------
 %%
-%% Extension:
-%% [{<<"foo">>, <<"bar">>}]   -> {"foo": "bar"} -> [{<<"foo">>, <<"bar">>}]
-%%
+%% null                       -> null           -> null
+%% true                       -> true           -> true
+%% false                      -> false          -> false
+%% "hi"                       -> [104, 105]     -> [104, 105]
+%% <<"hi">>                   -> "hi"           -> <<"hi">>
+%% hi                         -> "hi"           -> <<"hi">>
+%% 1                          -> 1              -> 1
+%% 1.25                       -> 1.25           -> 1.25
+%% []                         -> []             -> []
+%% [true, 1.0]                -> [true, 1.0]    -> [true, 1.0]
+%m [{}]                       -> {}             -> [{}]
+%a [{<<"foo">>, <<"bar">>}]   -> {"foo": "bar"} -> [{<<"foo">>, <<"bar">>}]
+%% #{<<"foo">> => <<"bar">>}  -> {"foo": "bar"} -> #{<<"foo">> => <<"bar">>}
+%m #{<<"foo">> => [{}]}       NOT SUPPORT
 %%--------------------------------------------------------------------
 
 all() -> emqx_ct:all(?MODULE).
@@ -63,9 +81,8 @@ t_decode_encode(_) ->
     1.25 = decode(encode(1.25)),
     [] = decode(encode([])),
     [true, 1] = decode(encode([true, 1])),
-    [] = decode(encode({[]})),
-    [{<<"foo">>, <<"bar">>}] = decode(encode({[{foo, bar}]})),
-    [{<<"foo">>, <<"bar">>}] = decode(encode({[{<<"foo">>, <<"bar">>}]})),
+    [{}] = decode(encode([{}])),
+    [{<<"foo">>, <<"bar">>}] = decode(encode([{foo, bar}])),
     [{<<"foo">>, <<"bar">>}] = decode(encode([{<<"foo">>, <<"bar">>}])),
     [[{<<"foo">>, <<"bar">>}]] = decode(encode([[{<<"foo">>, <<"bar">>}]])),
     [[{<<"foo">>, <<"bar">>},
@@ -92,10 +109,10 @@ t_safe_decode_encode(_) ->
     1.25 = safe_encode_decode(1.25),
     [] = safe_encode_decode([]),
     [true, 1] = safe_encode_decode([true, 1]),
-    [] = safe_encode_decode({[]}),
-    [{<<"foo">>, <<"bar">>}] = safe_encode_decode({[{foo, bar}]}),
-    [{<<"foo">>, <<"bar">>}] = safe_encode_decode({[{<<"foo">>, <<"bar">>}]}),
+    [{}] = decode(encode([{}])),
+    [{<<"foo">>, <<"bar">>}] = safe_encode_decode([{foo, bar}]),
     [{<<"foo">>, <<"bar">>}] = safe_encode_decode([{<<"foo">>, <<"bar">>}]),
+    [[{<<"foo">>, <<"bar">>}]] = safe_encode_decode([[{<<"foo">>, <<"bar">>}]]),
     {ok, Json} = emqx_json:safe_encode(#{<<"foo">> => <<"bar">>}),
     {ok, #{<<"foo">> := <<"bar">>}} = emqx_json:safe_decode(Json, [return_maps]).
 
@@ -105,4 +122,3 @@ safe_encode_decode(Term) ->
         {ok, {NTerm}} -> NTerm;
         {ok, NTerm}   -> NTerm
     end.
-