emqx_utils_json.erl 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2018-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -module(emqx_utils_json).
  17. -compile(inline).
  18. -export([
  19. encode/1,
  20. encode/2,
  21. safe_encode/1,
  22. safe_encode/2
  23. ]).
  24. -compile(
  25. {inline, [
  26. encode/1,
  27. encode/2
  28. ]}
  29. ).
  30. -export([
  31. decode/1,
  32. decode/2,
  33. safe_decode/1,
  34. safe_decode/2
  35. ]).
  36. -compile(
  37. {inline, [
  38. decode/1,
  39. decode/2
  40. ]}
  41. ).
  42. -export([is_json/1]).
  43. -compile({inline, [is_json/1]}).
  44. -type encode_options() :: jiffy:encode_options().
  45. -type decode_options() :: jiffy:decode_options().
  46. -type json_text() :: iolist() | binary().
  47. -type json_term() :: jiffy:jiffy_decode_result().
  48. -export_type([json_text/0, json_term/0]).
  49. -export_type([decode_options/0, encode_options/0]).
  50. -spec encode(json_term()) -> json_text().
  51. encode(Term) ->
  52. encode(Term, [force_utf8]).
  53. -spec encode(json_term(), encode_options()) -> json_text().
  54. encode(Term, Opts) ->
  55. to_binary(jiffy:encode(to_ejson(Term), Opts)).
  56. -spec safe_encode(json_term()) ->
  57. {ok, json_text()} | {error, Reason :: term()}.
  58. safe_encode(Term) ->
  59. safe_encode(Term, [force_utf8]).
  60. -spec safe_encode(json_term(), encode_options()) ->
  61. {ok, json_text()} | {error, Reason :: term()}.
  62. safe_encode(Term, Opts) ->
  63. try encode(Term, Opts) of
  64. Json -> {ok, Json}
  65. catch
  66. error:Reason ->
  67. {error, Reason}
  68. end.
  69. -spec decode(json_text()) -> json_term().
  70. decode(Json) -> decode(Json, [return_maps]).
  71. -spec decode(json_text(), decode_options()) -> json_term().
  72. decode(Json, Opts) ->
  73. from_ejson(jiffy:decode(Json, Opts)).
  74. -spec safe_decode(json_text()) ->
  75. {ok, json_term()} | {error, Reason :: term()}.
  76. safe_decode(Json) ->
  77. safe_decode(Json, []).
  78. -spec safe_decode(json_text(), decode_options()) ->
  79. {ok, json_term()} | {error, Reason :: term()}.
  80. safe_decode(Json, Opts) ->
  81. try decode(Json, Opts) of
  82. Term -> {ok, Term}
  83. catch
  84. error:Reason ->
  85. {error, Reason}
  86. end.
  87. -spec is_json(json_text()) -> boolean().
  88. is_json(Json) ->
  89. element(1, safe_decode(Json)) =:= ok.
  90. %%--------------------------------------------------------------------
  91. %% Helpers
  92. %%--------------------------------------------------------------------
  93. -compile(
  94. {inline, [
  95. to_ejson/1,
  96. from_ejson/1
  97. ]}
  98. ).
  99. to_ejson([{}]) ->
  100. {[]};
  101. to_ejson([{_, _} | _] = L) ->
  102. {[{K, to_ejson(V)} || {K, V} <- L]};
  103. to_ejson(L) when is_list(L) ->
  104. [to_ejson(E) || E <- L];
  105. to_ejson(M) when is_map(M) ->
  106. maps:map(fun(_K, V) -> to_ejson(V) end, M);
  107. to_ejson(T) ->
  108. T.
  109. from_ejson(L) when is_list(L) ->
  110. [from_ejson(E) || E <- L];
  111. from_ejson({[]}) ->
  112. [{}];
  113. from_ejson({L}) ->
  114. [{Name, from_ejson(Value)} || {Name, Value} <- L];
  115. from_ejson(T) ->
  116. T.
  117. to_binary(B) when is_binary(B) -> B;
  118. to_binary(L) when is_list(L) ->
  119. iolist_to_binary(L).