I have an existing camelCase JSON API that I can’t change and I want to be able to continue to use elixir snake_case naming conventions. I am getting the JSON via UDP connection, and I send JSON responses back to that UDP endpoint. I am currently using Jason directly. It was included in the template, so I went with it. I figured out that I could provide my own decode function for keys so that I can change the JSON key to snake_case and run String.to_existing_atom/1. However this doesn’t appear to be an option in the encoding. I did find Convert camel case to underscore in json but it mostly talks about how to convert from camelCase to snake_case. It doesn’t talk about integrating into the JSON encoding. I could just recursively rebuild the entire struct into a map changing the keys, but that sounds like it would kill performance. Is there something I am missing? Should I just recursively convert each JSON payload I am sending? Should I switch to Poison? Should I not care about snake_case convention in Elixir?
I can relate to machine performance anxiety but I suggest you directly go this route and measure. Benchee will help.
Personally I’d go for:
def to_atom_map(%{
"firstName" => first_name,
"lastName" => last_name
%}) do
%{
first_name: first_name,
last_name: last_name
}
end
and vice versa.
You might enjoy checking out recase:
Here’s a quick script to show how you could use it
Mix.install([:recase, :jason])
Recase.Enumerable.convert_keys(
%{"yourKey" => "value"},
&Recase.to_snake/1
)
|> IO.inspect(label: "res")
json =
Recase.Enumerable.convert_keys(
%{my_key: "value"},
&Recase.to_camel/1
)
|> IO.inspect(label: "to camel")
|> Jason.encode!()
IO.puts("Json: #{json}")
Running this prints out:
res: %{"your_key" => "value"}
to camel: %{myKey: "value"}
Json: {"myKey":"value"}
Thanks everyone for replying. I was busy with work stuff and just got back to this thread.
@dimitarvp I will probably end up biting the bullet and writing/generating this code. I started switching over to typed_struct so I wonder if I couldn’t make a plugin to do it for me.
@axelson Recase looked like it could easily do what I wanted. The only thing I was worried about was that I couldn’t use the String.to_existing_atom so that the BEAM VM can’t get blown up by a malicious actor. I didn’t see one at least. I am pretty new to Elixir though so I could have missed something.
@mhanberg just released a new blog post and mentions his library schematic. Maybe that could help.
Here’s the Blog Post: Credo Language Server and the birth of elixir-tools | Mitchell Hanberg
@kevinschweikert Schematic actually looks really cool. I might try it out later. I feel like I will just need to experiment with all these solutions.