Closed sezaru closed 3 years ago
It's not possible to override existing encoders. Additionally encoders for keys are completely different from regular encoders for values - in particular keys in objects in JSON are required to use string syntax, for example "2": ....
instead of regular integer encoding 2: ...
.
A way around this, I could see, would be to define a wrapper data structure that would handle the encoding. Something along the lines of:
defmodule Wrapper do
defstruct [:value]
def new(map) when is_map(map), do: %__MODULE__{value: map}
defimpl Jason.Encoder do
import Jason.Encode, only: [value: 2, string: 2]
def encode(%{value: map}, opts) do
case Map.to_list(map) do
[] ->
"{}"
[{key, value} | rest] ->
["{", key(key, opts), ":", value(value, opts), encode_loop(rest, opts), "}"]
end
end
defp encode_loop([{key, value} | rest], opts) do
[",", key(key, opts), ":", value(value, opts) | encode_loop(rest, opts)]
end
defp key(:my_atom, _), do: ~S|"2"|
defp key(other, opts), do: string(to_string(other), opts)
end
end
This does a lot of the handling manually, but does avoid double traversal of the data structures. At this point, it's possible to wrap the maps where you need this special handling with Wrapper.new(map)
and pass that to Jason.encode!/2
.
I'm going to close this. If you have any follow-ups, please re-open.
Hello,
My program receives some maps that can contain some atoms in some values, for example:
I want to convert this map to json but I want to first convert these atoms to integer by a converter map, so let's say in this case :my_atom needs to be converted to number 2.
Since I don't want to traverse the whole map twice (since Jason will already do that), is it possible to handle this via a
Jason.Encoder
ou via some other way inside the Jasonencode!
call?I tried the following but without success:
Thanks