Edantic is a library for casting «plain» JSON-originated data into Elixir data structures with necessary validations.
Assume there is a module with a corresponding struct:
defmodule Person do
defstruct [
:age, :name, :department
]
@type first_name() :: String.t
@type second_name() :: String.t
@type t() :: %__MODULE__{
age: non_neg_integer(),
name: {first_name(), second_name()},
department: :finance | :it
}
end
And there is some JSON-originated data:
data = %{
"age" => 23,
"name" => ["girolamo", "savonarola"],
"department" => "it"
}
With Edantic we can simultaneously validate this data and convert it into Elixir structures:
import Edantic
{:ok, person} = Edantic.cast(Person.t(), data)
person == %Person{
age: 23,
name: {"girolamo", "savonarola"},
department: :it
}
data_bad_department = %{
"age" => 23,
"name" => ["girolamo", "savonarola"],
"department" => "unknown"
}
{:error, error} = Edantic.cast(Person.t(), data_bad_department)
error
|> Edantic.CastError.format()
|> IO.puts()
key-value pair does not match to any of the specified for the map
data: %{"department" => "unknown"}
type: %Edantic.Support.Types.Person{age: non_neg_integer(), department: :finance | :it, name: {first_name(), second_name()}}}
By «JSON-originated data» is denoted all the data matching the following type t()
:
@type key() :: String.t()
@type value() ::
String.t() | nil | boolean | integer() | float() | %{optional(key()) => value()} | [value()]
@type t() :: value()
Since plain data structures are rather poor, there are some automatic enrichments allowed while casting:
- Strings can be cast to corresponding atoms
"a" -> :a
. - Lists of suitable size can be cast to tuples
[1, "a"] -> {1, :a}
. - Maps can be cast to an arbitrary struct with the same set of fields
%{a: 123} -> %SomeSt{a: 123}
if fields pass validations.
Since type info is located in separate beam chunks which are stripped by default, be sure your releases do not strip them.
For example, by setting strip_beams
option to false
.
def project do
[
...
deps: deps(),
releases: [
release_name: [
strip_beams: false,
...
]
]
]
end
If available in Hex, the package can be installed
by adding edantic
to your list of dependencies in mix.exs
:
def deps do
[
{:edantic, "~> 0.1.0"}
]
end
Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/edantic.
This software is licensed under MIT License.