Packages
zoi
0.8.0
0.18.6
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.1
0.16.0
0.15.0
0.14.1
0.14.0
0.13.1
0.13.0
0.12.1
0.12.0
0.11.1
0.11.0
0.10.7
0.10.6
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.1
0.9.0
0.9.0-rc.1
0.9.0-rc.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.0
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
Zoi is a schema validation library for Elixir, designed to provide a simple and flexible way to define and validate data.
Current section
Files
Jump to
Current section
Files
README.md
# Zoi
<img src="https://github.com/phcurado/zoi/raw/main/guides/images/logo.png" alt="Zoi" width="150">
[](https://github.com/phcurado/zoi/actions/workflows/ci.yml)
[](https://coveralls.io/github/phcurado/zoi?branch=main)
[](https://hex.pm/packages/zoi)
[](https://hexdocs.pm/zoi)
[](https://hex.pm/packages/zoi)
---
<a href='https://ko-fi.com/R5R11AIF9P' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi6.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
`Zoi` is a schema validation library for Elixir, designed to provide a simple and flexible way to define and validate data.
## Installation
`zoi` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:zoi, "~> 0.8"}
]
end
```
## Usage
You can create schemas for various data types, including strings, integers, floats, booleans, arrays, maps, and more. `Zoi` supports a wide range of validation rules and transformations.
### Parsing Data
Here's a simple example of how to use `Zoi` to validate a string:
```elixir
# Define a schema with a string type
iex> schema = Zoi.string() |> Zoi.min(3)
iex> Zoi.parse(schema, "hello")
{:ok, "hello"}
iex> Zoi.parse(schema, "hi")
{:error, [%Zoi.Error{message: "too small: must have at least 3 characters"}]}
# Add transforms to a schema
iex> schema = Zoi.string() |> Zoi.trim()
iex> Zoi.parse(schema, " world ")
{:ok, "world"}
```
You can also validate structured maps:
```elixir
# Validate a structured data in a map
iex> schema = Zoi.object(%{name: Zoi.string(), age: Zoi.integer(), email: Zoi.email()})
iex> Zoi.parse(schema, %{name: "John", age: 30, email: "john@email.com"})
{:ok, %{name: "John", age: 30, email: "john@email.com"}}
iex> Zoi.parse(schema, %{email: "invalid-email"})
{:error, [
%Zoi.Error{path: [:name], message: "is required"},
%Zoi.Error{path: [:age], message: "is required"},
%Zoi.Error{path: [:email], message: "invalid email format"}
]}
```
and arrays:
```elixir
# Validate an array of integers
iex> schema = Zoi.array(Zoi.integer() |> Zoi.min(0)) |> Zoi.min(2)
iex> Zoi.parse(schema, [1, 2, 3])
{:ok, [1, 2, 3]}
iex> Zoi.parse(schema, [1, "2"])
{:error, [%Zoi.Error{path: [1], message: "invalid type: must be an integer"}]}
```
And many more possibilities, including nested schemas, custom validations and data transformations. Check the official [docs](https://hexdocs.pm/zoi) for more details.
## Types
`Zoi` can infer types from schemas, allowing you to leverage Elixir's `@type` and `@spec` annotations for documentation
```elixir
defmodule MyApp.Schema do
@schema Zoi.string() |> Zoi.min(2) |> Zoi.max(100)
@type t :: unquote(Zoi.type_spec(@schema))
end
```
This will generate the following type specification:
```elixir
@type t :: binary()
```
This also applies to complex types, such as `Zoi.object/2`:
```elixir
defmodule MyApp.User do
@schema Zoi.object(%{
name: Zoi.string() |> Zoi.min(2) |> Zoi.max(100),
age: Zoi.integer() |> Zoi.optional(),
email: Zoi.email()
})
@type t :: unquote(Zoi.type_spec(@schema))
end
```
Which will generate:
```elixir
@type t :: %{
required(:name) => binary(),
optional(:age) => integer(),
required(:email) => binary()
}
```
### Errors
When validation fails, `Zoi` returns a list of errors, each containing a message and the path to the invalid data. Even when erros are nested, `Zoi` will return all errors in a flattened list.
```elixir
iex> schema = Zoi.object(%{name: Zoi.string(), age: Zoi.integer()})
iex> Zoi.parse(schema, %{name: 123, age: "thirty"})
{:error, [
%Zoi.Error{path: [:name], message: "invalid type: must be a string"},
%Zoi.Error{path: [:age], message: "invalid type: must be an integer"}
]}
```
You can view the error in a map format using the `Zoi.treefy_errors/1` function:
```elixir
iex> Zoi.treefy_errors(errors)
%{
name: ["invalid type: must be a string"],
age: ["invalid type: must be an integer"]
}
```
You can also customize error messages:
```elixir
iex> schema = Zoi.string(error: "not a string")
iex> Zoi.parse(schema, :hi)
{:error, [%Zoi.Error{message: "not a string"}]}
```
### Metadata
You can attach metadata to schemas using the `:metadata` option. This metadata can be useful for documentation, testing, or other any purpose your application may require.
```elixir
iex> schema = Zoi.string(metadata: [id: "1", description: "A simple string"])
iex> Zoi.metadata(schema)
[id: "1", description: "A simple string"]
```
You can use this feature to create self-documenting schemas, with example and tests. For example:
```elixir
defmodule MyApp.UserSchema do
@schema Zoi.object(
%{
name: Zoi.string() |> Zoi.min(2) |> Zoi.max(100),
age: Zoi.integer() |> Zoi.optional()
},
metadata: [
example: %{name: "Alice", age: 30},
doc: "A user schema with name and optional age",
moduledoc: "Schema representing a user with name and optional age"
]
)
@moduledoc """
#{Zoi.metadata(@schema)[:moduledoc]}
"""
@doc """
#{Zoi.metadata(@schema)[:doc]}
"""
def schema, do: @schema
end
defmodule MyApp.UserSchemaTest do
use ExUnit.Case
alias MyApp.UserSchema
test "example matches schema" do
example = Zoi.metadata(UserSchema.schema())[:example]
assert {:ok, example} == Zoi.parse(UserSchema.schema(), example)
end
end
```
## Guides
Check the official guides for more examples and use cases:
- [Quickstart Guide](https://hexdocs.pm/zoi/quickstart_guide.html)
- [Using Zoi to generate OpenAPI specs](https://hexdocs.pm/zoi/using_zoi_to_generate_openapi_specs.html)
- [Validating controller parameters](https://hexdocs.pm/zoi/validating_controller_parameters.html)
- [Converting Keys From Object](https://hexdocs.pm/zoi/converting_keys_from_object.html)
- [Generating Schemas from JSON](https://hexdocs.pm/zoi/generating_schemas_from_json_example.html)
## Acknowledgements
`Zoi` is inspired by [Zod](https://zod.dev/) and [Joi](https://joi.dev/), providing a similar experience for Elixir.