xema v0.9.3 Xema View Source
A schema validator inspired by JSON Schema.
All available keywords to construct a schema are described on page Usage.
This module can be used to construct a schema module. Should a module
contain multiple schemas the option multi: true
is required.
use Xema
imports Xema.Builder
and extends the module with the functions
__MODULE__.valid?/2
__MODULE__.validate/2
__MODULE__.validate!/2
__MODULE__.cast/2
__MODULE__.cast!/2
The macro xema/2
supports the construction of a schema. After that
the schema is available via the functions above.
In a multi schema module a schema can be tagged with @default true
and
then called by
__MODULE__.valid?/1
__MODULE__.validate/1
__MODULE__.validate!/1
__MODULE__.cast/1
__MODULE__.cast!/1
The functions with arity 1 are also available for single schema modules.
Examples
Sinlge schema module:
iex> defmodule SingleSchema do
...> use Xema
...>
...> # The name :num is optional.
...> xema :num, do: number(minimum: 1)
...> end
iex>
iex> SingleSchema.valid?(:num, 6)
true
iex> SingleSchema.valid?(5)
true
iex> SingleSchema.validate(0)
{:error, %Xema.ValidationError{
reason: %{minimum: 1, value: 0}
}}
iex> SingleSchema.cast("5")
{:ok, 5}
iex> SingleSchema.cast("-5")
{:error, %Xema.ValidationError{
reason: %{minimum: 1, value: -5}
}}
Multi schema module:
iex> defmodule Schema do
...> use Xema, multi: true
...>
...> @pos integer(minimum: 0)
...> @neg integer(maximum: 0)
...>
...> @default true
...> xema :user do
...> map(
...> properties: %{
...> name: string(min_length: 1),
...> age: @pos
...> }
...> )
...> end
...>
...> xema :nums do
...> map(
...> properties: %{
...> pos: list(items: @pos),
...> neg: list(items: @neg)
...> }
...> )
...> end
...> end
iex>
iex> Schema.valid?(:user, %{name: "John", age: 21})
true
iex> Schema.valid?(%{name: "John", age: 21})
true
iex> Schema.valid?(%{name: "", age: 21})
false
iex> Schema.validate(%{name: "John", age: 21})
:ok
iex> Schema.validate(%{name: "", age: 21})
{:error, %Xema.ValidationError{
reason: %{
properties: %{name: %{min_length: 1, value: ""}}}
}
}
iex> Schema.valid?(:nums, %{pos: [1, 2, 3]})
true
iex> Schema.valid?(:nums, %{neg: [1, 2, 3]})
false
```
Link to this section Summary
Functions
Converts the given data using the specified schema. Returns {:ok, result}
or
{:error, reason}
. The result
is converted and validated with the schema.
Converts the given data using the specified schema. Returns the converted data or an exception.
This function creates the schema from the given data
.
Returns the source for a given xema
. The output can differ from the input
if the schema contains references. To get the original source the schema
must be created with inline: false
.
Returns true
if the value
is a valid value against the given schema
;
otherwise returns false
.
Returns :ok
if the value
is a valid value against the given schema
;
otherwise returns an error tuple.
Returns :ok
if the value
is a valid value against the given schema
;
otherwise raises a Elixir.Xema.ValidationError
.
Link to this section Types
t()
View Source
t() :: %Xema{refs: map(), schema: Xema.Schema.t()}
t() :: %Xema{refs: map(), schema: Xema.Schema.t()}
This struct contains the schema and references of the schema.
Link to this section Functions
cast(xema, value, opts \\ []) View Source
Converts the given data using the specified schema. Returns {:ok, result}
or
{:error, reason}
. The result
is converted and validated with the schema.
Examples:
iex> schema = Xema.new({:integer, minimum: 1})
iex> Xema.cast(schema, "5")
{:ok, 5}
iex> Xema.cast(schema, "five")
{:error, %Xema.CastError{
key: nil,
path: [],
to: :integer,
value: "five"
}}
iex> Xema.cast(schema, "0")
{:error, %Xema.ValidationError{
reason: %{minimum: 1, value: 0}
}}
Multiple types
If for a value multiple types are defined the function used the result of the first successful conversion.
Examples
iex> schema = Xema.new([:integer, :string, nil])
iex> Xema.cast(schema, 5)
{:ok, 5}
iex> Xema.cast(schema, 5.5)
{:ok, "5.5"}
iex> Xema.cast(schema, "5")
{:ok, 5}
iex> Xema.cast(schema, "five")
{:ok, "five"}
iex> Xema.cast(schema, nil)
{:ok, nil}
iex> Xema.cast(schema, [5])
{:error,
%Xema.CastError{path: [], to: [:integer, :string, nil], value: [5]}
}
Cast with any_of
, all_of
, and one_of
Schemas in a combiner will be cast independently one by one in reverse order.
Examples
iex> schema = Xema.new(any_of: [
...> [properties: %{a: :integer}],
...> [properties: %{a: :string}]
...> ])
iex> Xema.cast(schema, %{a: 5})
{:ok, %{a: 5}}
iex> Xema.cast(schema, %{a: 5.5})
{:ok, %{a: "5.5"}}
iex> Xema.cast(schema, %{a: "5"})
{:ok, %{a: 5}}
iex> Xema.cast(schema, %{a: "five"})
{:ok, %{a: "five"}}
iex> Xema.cast(schema, %{a: [5]})
{:error,
%Xema.CastError{
error: nil,
key: nil,
message: nil,
path: [],
to: [
%{path: [:a], to: :integer, value: [5]},
%{path: [:a], to: :string, value: [5]}
],
value: %{a: [5]}
}}
Options
With the option additional_properties: :delete
additional properties will be
deleted on cast. Additional properties will be deleted in schemas with
additional_properties: false
.
Examples
iex> schema = Xema.new(
...> properties: %{
...> a: [
...> properties: %{
...> foo: :integer
...> },
...> additional_properties: false
...> ],
...> b: [
...> properties: %{
...> foo: :integer
...> }
...> ]
...> }
...> )
iex>
iex> Xema.cast(schema, %{
...> a: %{foo: "6", bar: "7"},
...> b: %{foo: "6", bar: "7"},
...> }, additional_properties: :delete)
{:ok, %{
a: %{foo: 6},
b: %{foo: 6, bar: "7"}
}}
cast!(xema, value, opts \\ []) View Source
Converts the given data using the specified schema. Returns the converted data or an exception.
new(data, opts \\ [])
View Source
new(
Xema.Schema.t() | Xema.Schema.type() | tuple() | atom() | keyword(),
keyword()
) :: Xema.t()
new( Xema.Schema.t() | Xema.Schema.type() | tuple() | atom() | keyword(), keyword() ) :: Xema.t()
This function creates the schema from the given data
.
Possible options:
:loader
- a loader for remote schemas. This option will overwrite the loader from the config. See Configure a loader to how to define a loader.inline
- inlined all references in the schema. Default:true
.
Examples
Simple schema:
iex> schema = Xema.new :string
iex> Xema.valid? schema, "hello"
true
iex> Xema.valid? schema, 42
false
Schema:
iex> schema = Xema.new {:string, min_length: 3, max_length: 12}
iex> Xema.valid? schema, "hello"
true
iex> Xema.valid? schema, "hi"
false
Nested schemas:
iex> schema = Xema.new {:list, items: {:number, minimum: 2}}
iex> Xema.validate(schema, [2, 3, 4])
:ok
iex> Xema.valid?(schema, [2, 3, 4])
true
iex> Xema.validate(schema, [2, 3, 1])
{:error, %Xema.ValidationError{
reason: %{
items: [{2, %{value: 1, minimum: 2}}]}
}
}
More examples can be found on page Usage.
source(xema) View Source
Returns the source for a given xema
. The output can differ from the input
if the schema contains references. To get the original source the schema
must be created with inline: false
.
Examples
iex> {:integer, minimum: 1} |> Xema.new() |> Xema.source()
{:integer, minimum: 1}
valid?(schema, value)
View Source
valid?(Xema.t() | Xema.Schema.t(), any()) :: boolean()
valid?(Xema.t() | Xema.Schema.t(), any()) :: boolean()
Returns true
if the value
is a valid value against the given schema
;
otherwise returns false
.
validate(schema, value)
View Source
validate(Xema.t() | Xema.Schema.t(), any()) :: Xema.Validator.result()
validate(Xema.t() | Xema.Schema.t(), any()) :: Xema.Validator.result()
Returns :ok
if the value
is a valid value against the given schema
;
otherwise returns an error tuple.
validate!(xema, value)
View Source
validate!(Xema.t() | Xema.Schema.t(), any()) :: :ok
validate!(Xema.t() | Xema.Schema.t(), any()) :: :ok
Returns :ok
if the value
is a valid value against the given schema
;
otherwise raises a Elixir.Xema.ValidationError
.