Xema and JsonXema - Schema validatiors

JsonXema is a JSON Schema validator with support for draft 04, 06, and 07. JsonXema based on elixir schema validator Xema.

https://github.com/hrzndhrn/json_xema

Xema is a schema validator inspired by JSON Schema. In Xema schemas can be created in Elixir and any data structure can be validated.

https://github.com/hrzndhrn/xema

Feedback, critic, improvements and PRs are very welcome, thanks!

9 Likes

I’d be interested in seeing a side-by-side comparison between Xema and Ecto’s validation.

3 Likes

The Xema library was updated to 0.8.0 and works now with inlined references to speed up validation. That also affects JsonXema see benchmark.

Xema also supports now custom validators. There is an example on the examples page in the online docs.

2 Likes

Thanks for working on this! I wanted to try JSON Schema with my new personal project, and was disappointed to see the top Google result is a few specifications out-of-date. Glad I searched here on the forum!

3 Likes

Hello @repromancer . You are welcome. I am happy if you find the lib helpful. Feel free to report everything you like or don’t like. In the next version, I will improve the error messages for validation errors. For now, it can be hard in big schemas to figure where the error in the data is.

Will do!

Xema 0.9.0 is released. The new version comes with some breaking changes, see changelog.

New features

  • convert data with Xema.cast
  • nice error messages

Example:

iex> defmodule Person do
...>   use Xema
...>
...>   xema do
...>     map(
...>       keys: :atoms,
...>       properties: %{
...>         name: string(),
...>         age: integer(minimum: 0),
...>         fav: atom(enum: [:erlan, :elixir, :js, :rust, :go])
...>       }
...>     )
...>   end
...>
...>   def new(args), do: cast!(args)
...> end
iex>
iex> person = Person.new(name: "Joe", age: 24, fav: :elixir) 
%{
  age: 24,
  fav: :elixir,
  name: "Joe"
}
iex> json = person |> Jason.encode!() |> Jason.decode()
%{
  "age" => 24,
  "fav" => "elixir",
  "name" => "Joe"
}
iex> Person.cast!(json)
%{
  age: 24,
  fav: :elixir,
  name: "Joe"
}
iex> {:error, error} = Person.validate(%{name: 42, age: -1, fav: :php})
iex> Exception.message(error) 
"""
Value -1 is less than minimum value of 0, at [:age].
Value :php is not defined in enum, at [:fav].
Expected :string, got 42, at [:name].\
"""

More examples can be found at section Cast and Examples - Cast JSON.

4 Likes

The new release of Xema adds the macros field and required to create struct schemas.

iex> defmodule StructA do
...>   use Xema
...>
...>   xema do
...>     field :foo, :integer, minimum: 0
...>   end
...> end
...>
...> defmodule StructB do
...>   use Xema
...>
...>   xema do
...>     field :a, :string, min_length: 3
...>     field :b, StructA
...>     required [:a]
...>   end
...> end
...>
...> data = StructB.cast!(a: "abc", b: %{foo: 5})
...> data.a
"abc"
iex> Map.from_struct(data.b)
%{foo: 5}

A more extensive example can be found at Examples > Struct

2 Likes