Parameter is a library for dealing with parameter serialization, deserialization and validation following a structure very similar to Ecto schema.
The main motivation for creating this is to have more options when loading external parameters and convert it to plain elixir maps or structure. It can load the data to a map or struct, transform external data keys to elixir keys, perform validations and dump the data.
The idea is to create a schema that models the data you need to load on your elixir application. The “key” field on the schema is useful to map keys that comes with a different format of your schema keys. For example when external data have camelCase
keys and you want to use snake_case
.
As an example imagine you are making and http request to a rest API to fetch a single user, this is how you can model the User schema:
defmodule User do
use Parameter.Schema
alias Parameter.Validators
param do
field :first_name, :string, key: "firstName", required: true
field :last_name, :string, key: "lastName"
field :email, :string, validator: &Validators.email(&1)
has_one :address, Address do
field :city, :string, required: true
field :street, :string
field :number, :integer
end
end
end
And this is how the external data could look like:
params = %{
"firstName" => "John",
"lastName" => "Doe",
"email" => "john@email.com",
"address" => %{"city" => "New York", "street" => "Broadway"}
}
Now this params can be deserialized using the load/2
function
iex> Parameter.load(User, params)
{:ok, %{
first_name: "John",
last_name: "Doe",
email: "john@email.com",
address: %{city: "New York", street: "Broadway"}
}}
the camelCase
keys were converted to snake_case
keys as per schema definition. If the external data already have the same key type as the schema definition this param can be ignored.
It also possible to load the schema as structure:
iex> Parameter.load(User, params, struct: true)
{:ok, %User{
first_name: "John",
last_name: "Doe",
email: "john@email.com",
address: %User.Address{city: "New York", street: "Broadway", number: nil}
}}
Also can be used on Phoenix APIs that needs to validate parameters before sending it to the context module.
defmodule MyProjectWeb.UserController do
use MyProjectWeb, :controller
import Parameter.Schema
alias MyProject.Users
param UserParams do
field :first_name, :string, required: true
field :last_name, :string, required: true
end
def create(conn, params) do
with {:ok, user_params} <- Parameter.load(__MODULE__.UserParams, params),
{:ok, user} <- Users.create_user(user_params) do
render(conn, "user.json", %{user: user})
end
end
end
There are plenty of more options available as built in validators (or possibility for creating custom ones), custom types, error handling, unknown options that comes from external data and serializing (dump) the data.