poison icon indicating copy to clipboard operation
poison copied to clipboard

Alphabetical sorting order for keys

Open pulzzejason opened this issue 7 years ago • 1 comments

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
}

pulzzejason avatar Dec 19 '17 21:12 pulzzejason

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)

ivan avatar Dec 19 '17 21:12 ivan