Closed randysecrist closed 4 years ago
fyi: for now, my particular project has jsx in the beam path - so I can just pass the KW list to it ... but I'd like to find a jason
way of doing this if possible.
I can add a protocol for Tuple but I don't have any way to converting the overall Keyword list with the flat Key/Value list into a single JSON object ...
Convert it to a map first then. Keyword lists aren't handled by Jason because they allow duplicates, and JSON object's don't, so you need to deal with it before-hand to make it unambiguous, and thus to convert to a json object then you want to convert the keyword list into a map, which is as simple as just passing the keyword list into Map.new(...)
.
"#{k}"
Also be very very very careful here, this is just absolutely ripe waiting for an atom exhaustion attack. You don't want to dynamically create atoms unless it's at compile-time only.
my_map |> Enum.sort |> Enum.flat_map(fn({k,v}) -> ["#{k}": v] end)
Also, why are you sorting it, JSON objects are specifically unsorted by the spec and doing otherwise is not following the spec (plus it won't work in this case anyway), thus it's a wasted operation, why not just pass my_map
in straight, assuming it is a map? ^.^;
Convert it to a map first then. Keyword lists aren't handled by Jason because they allow duplicates, and JSON object's don't, so you need to deal with it before-hand to make it unambiguous, and thus to convert to a json object then you want to convert the keyword list into a map, which is as simple as just passing the keyword list into
Map.new(...)
.
The KW list is assembled prior to this via a series of merged maps (equiv of using a set) so duplicates won't be an issue. I noticed there are options passed around; I haven't used jason
long enough to know if it has a strict mode or not but that would be handy to have documented somewhere....?
Also be very very very careful here, this is just absolutely ripe waiting for an atom exhaustion attack. You don't want to dynamically create atoms unless it's at compile-time only.
I get that ... keyspace is constrained however do I'm not worried about atom exhaustion. App is very purpose built and that has all been worked out already; and also not the problem I am solving here.
my_map |> Enum.sort |> Enum.flat_map(fn({k,v}) -> ["#{k}": v] end)
Also, why are you sorting it, JSON objects are specifically unsorted by the spec and doing otherwise is not following the spec (plus it won't work in this case anyway), thus it's a wasted operation, why not just pass
my_map
in straight, assuming it is a map? ^.^;
I'm sorting the attributes for occasional human consumption; its a requirement in my case to do so & many other encoders support it.
I'm totally fine if jason
doesn't want to support it .. I just need to know that so I can adjust as needed.
You can achieve this with a custom struct for the keyword and an encoder implementation. Something like:
defmodule SortedObject do
defstruct [:value]
def new(value), do: %__MODULE__{value: value}
defimpl Jason.Encoder do
def encode(%{value: value}, opts) do
Jason.Encode.keyword(Enum.sort(value), opts)
end
end
end
## Used as:
Jason.encode!(SortedObject.new(%{a: 1, b: 2}))
As this is possible to do with relatively little code, I'm not planning on adding something built-in to Jason for this at this time.
👍 - thanks for the clarification!
@michalmuskala Is there a plan to release the next version to hex? It looks like keyword lists, which you used in your solution above, were pushed a year ago but have never been released to hex.
I've been futzing with the use case of rendering json where the keys are sorted via Keyword list. So far this has been one of the only encoding cases I haven't been able to get
jason
to doCurrently ...
my_map |> Enum.sort |> Enum.flat_map(fn({k,v}) -> ["#{k}": v] end)
spits out a keyword list which is sorted by map key ...However each element is also a
Tuple
andjason
doesn't have a protocol built for handling tuples. I can add a protocol forTuple
but I don't have any way to converting the overall Keyword list with the flat Key/Value list into a single JSON object ...I'm not exactly clear on how I should implement the protocol for
Jason.Encoder
.. or how exactly to proceed. Hacking on this I usually end up converting the Keyword list back to a Map which has unsorted values.I see some recent work was done to add Keyword list support but the test case looks off ... the input is a struct (which is a map).
What are your thoughts on getting keyword lists as a supported term? How should I be going about this if
jason
is my only encoder/decoder?