:null atom and JSON
grepz opened this issue · 0 comments
Hello, i have following problem that I cannon solve right now due to specifics of handling null and nil in projects which uses both erlang land elixir libs.
Situation:
there are both erlang and elixir projects.
Both type of projects uses same erlang library.
Erlang library is using jiffy as a library of choice to handle JSON encoding/decoding, jiffy, being erlang library, handles JSON null values as null atoms in erlang terms, and vice versa.
Elixir projects are mostly using Poison for handling their HTTP responses, and Poison on the other hand handles JSON null value as nil and vice versa. Data from library's jiffy goes to Poison http encoder. Thus creating a problem with nil/null, since null atom for Poison is a string.
I can set jiffy to produce nil's instead of null's(use_nil option for decoder/encoder), but that will break erlang projects that are using same library, since they don't expect to meet nil's in place of null's.
It would be great to have use_null option in poison to be able to override this madness.
Problem example:
:jiffy.decode("{\"key\":null}", [:return_maps]) |> Poison.encode
{:ok, "{\"key\":\"null\"}"}
Naive approach to handle such situation will be:
@typep indent :: non_neg_integer
@typep offset :: non_neg_integer
@typep strict_keys :: boolean
+ @typep use_null :: boolean
@type options :: %{
optional(:escape) => escape,
optional(:pretty) => pretty,
optional(:indent) => indent,
optional(:offset) => offset,
- optional(:strict_keys) => strict_keys
+ optional(:strict_keys) => strict_keys,
+ optional(:use_null) => use_null
}
@spec encode(t, options) :: iodata
@@ -102,6 +104,12 @@ defimpl Poison.Encoder, for: Atom do
def encode(nil, _options), do: "null"
def encode(true, _options), do: "true"
def encode(false, _options), do: "false"
+ def encode(:null, options) do
+ case Map.get(options, :use_null, false) do
+ true -> "null"
+ false -> Poison.Encoder.BitString.encode("null", options)
+ end
+ end
def encode(atom, options) do
Poison.Encoder.BitString.encode(Atom.to_string(atom), options)
I understand that it affects performance, but right now can't find a way to solve problem without it.
I've tried to introduce conditional macros on erlang library side(LIBRARY_ENV_TYPE=(elixir|erlang) which must be set/overriden in project that is using this library(rebar's overrides), but it seems mix does not support overrides in any way.