JSV.Resolver.Local (jsv v0.7.2)

View Source

This module allows to build JSV.Resolver implementations that resolves schemas based on disk based on their $id property. It is not itself a JSV.Resolver implementation.

To define your own local resolver, use this module by providing the :source option with a path to a directory, a path to a file, or a list of paths to directories and files:

schemas_dir = "priv/messaging/schemas"
other_schema = "priv/users/user-schema.schema.json"

defmodule MyApp.LocalResolver do
  use JSV.Resolver.Local, source: [schemas_dir, other_schema]
end

The macro will read all .json files from the given sources and build an index mapping the $id property of each schema to its JSON-deserialized value.

For convenience, nested lists are accepted. Duplicated files accepted as well but not duplicates due to symlinks.

Compilation and caching

Schemas are loaded directly into the generated module code. The module will recompile everytime a loaded schema file is modified or deleted.

Recompilation will also happen when new files are added in directories listed as sources.

Debugging

The use JSV.Resolver.Local also accepts the following options:

  • :warn - A boolean flag enabling compilation warnings when a .json file cannot be read or loaded properly. Defaults to true.
  • :debug - A boolean flag enabling printouts of the loaded schemas on compilation. Defaults to false.

Example

The "priv/schemas/user-schema.schema.json" file contains the following JSON text:

{
  "$id": "myapp:user-0.0.1",
  "type": "object",
  "properties": {
    "username": {
      "type": "string"
    }
  }
}

Then this can be used as a source in your module.

defmodule MyApp.LocalResolver do
  use JSV.Resolver.Local, source: "priv/schemas"
end

You can now build validation roots (JSV.Root) by referencing this user schema in $ref and by providing your resolver to the JSV.build!/2 function:

iex> schema = %{"$ref" => "myapp:user-0.0.1"}
iex> root   = JSV.build!(schema, resolver: MyApp.LocalResolver)
iex> # Here we pass an invalid username (an integer)
iex> result = JSV.validate(%{"username" => 123}, root)
iex> match?({:error, %JSV.ValidationError{}}, result)
true

You can also directly fetch a schema from the defined module:

iex> MyApp.LocalResolver.resolve("myapp:user-0.0.1")
{:ok,
  %{
    "$id" => "myapp:user-0.0.1",
    "type" => "object",
    "properties" => %{"username" => %{"type" => "string"}}
  }}

iex> MyApp.LocalResolver.resolve("myapp:other")
{:error, {:unknown_id, "myapp:other"}}

Remember that schemas are identified and resolved by their $id property and not their path.