Ordering keys when encoding a map to json with Poison
Asked Answered
R

1

7

For reading purposes I would like to have a specific key order into the json file.

I know that map's key doesn't have any order and then we should not rely on that, but since Poison is not able to encode proplists I don't see how to do this.

iex(1)> %{from: "EUR", to: "USD", rate: 0.845} |> Poison.encode!
"{\"to\":\"USD\",\"rate\":0.845,\"from\":\"EUR\"}"

The result I would like is :

"{\"from\":\"EUR\", \"to\":\"USD\", \"rate\":0.845}"

Which structure should I use in order to achieve this with Poison ?

Rectus answered 26/5, 2016 at 9:44 Comment(0)
E
2

Are you sure you want to do this? Probably the least bad way to do it would be to define a struct for your map, and then implement the Poison encode protocol for that struct.

It might look something like this...

defmodule Currency do
    defstruct from: "", to: "", rate: 0
end

then somewhere in your project implement the protocol

defimpl Poison.Encoder, for: Currency do
  def encode(%Currency{from: from, to: to, rate: rate}, _options) do
    """
      {"from": #{from}, "to": #{to}, "rate": #{rate}}
    """
  end
end

and then

Poison.encode!(%Currency{from: "USD", to: "EUR", rate: .845})

All that being said, I'd really, really recommend against doing this. Ordered maps are always a terrible idea, and lead to some really brittle and confusing behavior.

Consider using something that's actually ordered, like a list of lists

Embryo answered 20/7, 2016 at 17:13 Comment(1)
I have also have this requirement in a sense. We're storing loads of tiny JSON objects (tick data) in plain text files. By ordering the fields in a certain way makes the tick data sortable without the need to unpack/decode the JSON which saves a huge amount of processing power and also makes it possible to use simple string comparison on the encoded data. Most often I would however agree with you that it should probably not be done lightly.Nealon

© 2022 - 2024 — McMap. All rights reserved.