Closed dennisxtria closed 4 years ago
Do you mean when encoding? Right now there's generally no transformation performed on keys when encoding besides converting to strings according to the String.Chars
protocol.
If you're asking about decoding, there's already an option where you can provide a function for transforming keys - the primary use-case is to change keys to atoms, but it could also be used to change casing.
Hi! Yes, I meant when encoding, sorry for not making it clear. In a few projects, where I use Jason, there is value in camelCase JSON and the frontend expects it accordingly. Thank you for your response and your time.
Something you could do until this is supported:
This doesn't necessarily solve the problem (there is PR up it seems) but one way to handle this from a JS perspective:
// you can cast vars while destructuring
const {
foo_bar: fooBar,
bar_baz: barBaz,
} = data;
const someApiData = {
fooBar,
barBaz,
};
// pretend you have a redux store or something
this.props.dispatch({
type: 'STORE_SOME_API_DATA',
someApiData,
});
However if jason does convert to camel case, it could be just as easy as:
const someApiData = { ...data };
Just food for thought 🙏
Hi Michal, any chance you're interested in something like this landing in the library? Our use case is that most APIs out there expect camelCase keys. One approach is of course to transform the keys in the map before encoding, but this is more inefficient I guess.
@michalmuskala: we would be interested in reviving PR #56 if this is something you would consider merging.
Does you like that approach? It seems like it would match well with the existing option in decode
mentioned above...
The big issue is that options like this wouldn't be supported in derived struct implementations (since they pre-encode keys at compile-time). Not to mention things like Jason.Fragment
that are completely pre-encoded. So it's problematic to support those things in a uniform way that wouldn't be surprising in some circumstances.
One possible way to handle this is similar to the solution I propsoed in #119:
Build a wrapper for maps, where this special handling is required, that hijacks the JSON generation though the protocol:
defmodule Wrapper do
defstruct [:value]
def new(map) when is_map(map), do: %__MODULE__{value: map}
defimpl Jason.Encoder do
import Jason.Encode, only: [value: 2, string: 2]
def encode(%{value: map}, opts) do
case Map.to_list(map) do
[] ->
"{}"
[{key, value} | rest] ->
["{", key(key, opts), ":", value(value, opts), encode_loop(rest, opts), "}"]
end
end
defp encode_loop([{key, value} | rest], opts) do
[",", key(key, opts), ":", value(value, opts) | encode_loop(rest, opts)]
end
defp key(other, opts), do: string(camelize(to_string(other)), opts)
defp camelize(string), do: .... # do actual conversion to camelCase
end
end
This does a lot of the handling manually, but does avoid double traversal of the data structures and should have comparable performance to native encoders in Jason itself. At this point, it's possible to wrap the maps where you need this special handling with Wrapper.new(map)
and pass that to Jason.encode!/2
.
Because of the concerns stated above, I don't think we'll have a built-in option for key conversion on encoding in Jason itself. I'm therefore going to close the issue.
Hello Michał,
I was wondering if there are any plans to provide an option for selecting key formatting for maps.
Best regards, Dennis