Current section
Files
Jump to
Current section
Files
lib/encoder.ex
defmodule Morpheus.Encoder do
@moduledoc """
Transforms JSON responses in Phoenix applications from Elixir's snake_case to JavaScript's camelCase format.
This module allows you to work with idiomatic Elixir snake_case in your codebase
while serving camelCase JSON to your API clients.
## Setup
In your config/config.exs, add after Jason config:
config :phoenix, :format_encoders, json: Morpheus.Encoder
That's it! Your JSON responses will now automatically convert keys to camelCase.
## Usage
### In Phoenix Controllers
# No Changes required
def show(conn, _params) do
user = %{
user_id: 1,
first_name: "John",
last_name: "Doe"
}
json(conn, user)
end
### In JSON Views
# No Changes required
defmodule MyAppWeb.UserJSON do
def show(%{user: user}) do
%{data: data(user)}
end
defp data(%User{} = user) do
%{
id: user.id,
first_name: user.first_name,
last_name: user.last_name
}
end
end
### Direct Usage
# For manual encoding when needed
Morpheus.Encoder.encode(%{user_name: "John"})
## How it Works
When Phoenix renders a JSON response, it uses this encoder which:
1. Recursively traverses all maps and lists in the data structure
2. Converts all keys from snake_case to camelCase
3. Passes the transformed data to Jason for final JSON encoding
## Configuration Options
You can configure encoding options in your config:
config :morpheus, encode_options: [pretty: true] # Passes these options to Jason.encode!/2
"""
@doc """
Encodes the given data structure to JSON with snake_case keys converted to camelCase.
This function is called automatically by Phoenix when rendering JSON responses.
## Parameters
* `data` - The Elixir data structure to be encoded
* `opts` - Optional keyword list of options to be passed to `Jason.encode!/2`
## Examples
iex> data = %{user_name: "John Doe", age: 30}
iex> Morpheus.Encoder.encode(data)
"{\"age\":30,\"userName\":\"John Doe\"}"
# With pretty printing
iex> data = %{user_name: "John Doe"}
iex> Morpheus.Encoder.encode(data, pretty: true)
\"\"\"
{
"userName": "John Doe"
}
\"\"\"
# Nested structures
iex> data = %{user_info: %{first_name: "John"}}
iex> Morpheus.Encoder.encode(data)
"{\"userInfo\":{\"firstName\":\"John\"}}"
"""
def encode(data, opts \\ []) do
data
|> Morpheus.convert_map_keys(&Morpheus.snake_to_camel/1)
|> Jason.encode!(opts)
end
@doc """
Encodes the given data structure to JSON with snake_case keys converted to camelCase,
returning an iodata.
This is useful when you want to avoid creating an intermediate binary string,
especially when dealing with large data structures.
## Parameters
* `data` - The Elixir data structure to be encoded
## Examples
# Basic usage
iex> data = %{user_name: "John"}
iex> iodata = Morpheus.Encoder.encode_to_iodata!(data)
iex> IO.iodata_to_binary(iodata)
"{\"userName\":\"John\"}"
# With nested structures
iex> data = %{user_info: %{first_name: "John"}}
iex> iodata = Morpheus.Encoder.encode_to_iodata!(data)
iex> IO.iodata_to_binary(iodata)
"{\"userInfo\":{\"firstName\":\"John\"}}"
"""
def encode_to_iodata!(data) do
data
|> Morpheus.convert_map_keys(&Morpheus.snake_to_camel/1)
|> Jason.encode_to_iodata!()
end
end