Storing Keyword lists in json(b) (?) column

In “the other language” for an already long time one can rely on the order of key-value pairs in the Map equivalent so getting keys returns them in the order the data structure was created so I never had problems serialising them into JSON and storing in jsonb columns. In Elixir (and apparently in Erlang) this is not the case though. Hence if I can’t rely on the order of keys in Map then Keyword to the rescue! Now I have the same data wrapped in keyword lists. This is still OK as they are relatively small so traversing them when accessing arbitrary elements is not a show-stopper. All works. And here comes the moment when I need to persist them to the database. “Normally” I’d use jsonb column for storing Maps but how do you suggest storing Keyword?

FWIW, JSON also provides 0 guarantees about key order within maps, it’s entirely implementation specific. Postgres could change their mind about jsonb tomorrow and technically be spec compliant.

If order is genuinely important I’d have a list of objects like [{"key":"foo","value":1},..]. This way you are depending on behavior not guaranteed by the JSON spec.

6 Likes

Heh, you might be right. I probably overstretched my memory and extrapolated too far from the fact that “Hash” preserves the order. Need to dig out how I did it in the past, tnx.

Just for completeness sake: Jason does support decoding json to a OrderedObjects struct and encode back, which can be used to maintain order, given that property is useful around caching / doing minimal changes to json data, which can be totally unrelated to the fact that consumers of the json data cannot rely on the order.

1 Like

I’d probably have to write my own serialiser/deserialiser too… Was wondering if there’s something first-party (like Ecto itself) already available

Right! Something like this:

https://hexdocs.pm/jason/Jason.OrderedObject.html

A wrapper around a keyword (that supports non-atom keys) allowing for proper protocol implementations.

Implements the Access behaviour and Enumerable protocol with complexity similar to keywords/lists.

OK, so… @benwilson512 is obviously right: “jsonb does not preserve white space, does not preserve the order of object keys […]”, and - yes - it was json, not jsonb what I used to use for such cases. @LostKobrakai is as usual :wink: right too. Jason.OrderedObject works as expected, and since Jason is already a dependency that fits my bill too. Summing up. Jason.OrderedObject combined with json column (although I guess even a varchar() would do here) works well for the case at hand. As always - thank you guys for valuable input!