poison
poison copied to clipboard
Alphabetical sorting order for keys
I would like to print out the JSON maps in alphabetical order.
I noticed that the encode function will always return the keys in reverse order. Am I missing something? I'm surprised that an option for alphabetical order hasn't been requested already.
iex(15)> %{"a"=>1,"b"=>2} |> Poison.encode!()
"{\"b\":2,\"a\":1}"
iex(16)> %{"b"=>1,"a"=>2} |> Poison.encode!()
"{\"b\":1,\"a\":2}"
iex(23)> %{} |> Map.put("a", 1) |> Map.put("c", 3) |> Map.put("b", 2) |> Poison.encode!(pretty: true) |> IO.puts
{
"c": 3,
"b": 2,
"a": 1
}
Add more keys and you will hit a threshold at which they're no longer in a discernible order; https://github.com/devinus/poison/issues/21#issuecomment-66900703
I have also needed this, though, when I was writing some tests that embedded JSON inside another document. I used this function to encode:
@doc """
Encode a map to JSON with all of the keys in alphabetical order
(including for objects nested inside this object).
"""
def encode_object_in_alphanumeric_key_order(obj) when is_map(obj) do
az_keys = obj |> Map.keys |> Enum.sort
iodata = [
"{",
Enum.map(az_keys, fn k ->
v = obj[k]
[Poison.encode!(k), ":", encode_object_in_alphanumeric_key_order(v)]
end) |> Enum.intersperse(","),
"}"
]
IO.iodata_to_binary(iodata)
end
def encode_object_in_alphanumeric_key_order(obj), do: Poison.encode!(obj)