# `Formata.Schema.JSONSchema`
[🔗](https://github.com/gsmlg-dev/formata/blob/v0.1.0/lib/formata/schema/json_schema.ex#L1)

JSON Schema documents compiled and validated by `Formata.Backplane.JsonSchema`.

Documents are JSON-compatible maps (string keys) or the boolean schemas
`true`/`false`. They are handed to `Formata.Backplane.JsonSchema` as they are; Formata
never converts them to native schemas.

## Dialects

Draft 2020-12 and Draft 7 are supported.

  * A recognized root `$schema` selects the dialect:
    `https://json-schema.org/draft/2020-12/schema` or
    `http://json-schema.org/draft-07/schema#`.
  * `dialect: :draft7 | :draft2020_12` selects it explicitly. Conflicting with
    the document's `$schema` is a `:schema` / `:dialect_conflict` error.
  * Without either, Draft 2020-12 is used.
  * A `$schema` that is not one of the recognized meta-schemas is rejected
    (`:schema` / `:unknown_dialect`) unless `dialect:` is given or a `:loader`
    is provided to resolve the custom meta-schema and its vocabularies.

Unknown keywords and extension keywords (for example `x-*`) are accepted as
annotations, as the dialects permit.

## Format assertion

`format` is an annotation by default and does not reject data.
Pass `format_assertion: true` to assert the formats implemented by
`Formata.Backplane.JsonSchema` (`email`, `date-time`, `date`, `time`, `uri`, `ipv4`,
`ipv6`, `hostname`, `regex`, `uuid`, ...). Unknown format names are always
accepted. In Draft 2020-12, a custom meta-schema that enables the
format-assertion vocabulary also enables assertion; a document without
`$schema` uses the standard vocabularies, in which `format` is an annotation.

Internationalized names cannot be checked without the IDNA2008 Unicode
tables, which Formata does not include. When `hostname`, `email`,
`idn-hostname`, or `idn-email` is asserted and the value contains an A-label
(`xn--...`) or a non-ASCII label, validation stops with a single
`:unsupported` / `:unsupported_format` error at the value's path: the value
is neither accepted nor rejected as if it had been checked, and the result
cannot be inverted by `not`, `anyOf`, `oneOf`, or `if`. A value that is
invalid for another reason (for example an ASCII label with `_`) is still a
`:validation` / `:format` error. Plain ASCII host names are fully checked.

## References

Local references (`#/$defs/...`, `#anchor`, embedded `$id` resources) are
resolved without any I/O. Remote references are only loaded through an
explicit `:loader` function `(uri -> {:ok, map | boolean} | {:error, term})`;
Formata performs no network access. A reference that cannot be resolved fails
validation with a `:schema` / `:unresolved_ref` error, never a silent pass.

## Defaults and other annotations

`default`, `examples`, `title`, and other annotations never modify data.
`Formata.cast/3` is not available for JSON Schemas because they define no
transformations.

## Data model

Data must be in the JSON data model: `nil`, booleans, numbers, strings,
lists, and maps with string keys. Other terms (atom keys, `Date`, tuples,
special-float atoms, ...) are reported as `:unsupported` / `:non_json_value`;
convert them explicitly first (see `Formata.Transform`).

Additional properties are governed only by the document
(`additionalProperties`, `unevaluatedProperties`); there is no facade option
that overrides them.

# `compile`

```elixir
@spec compile(map() | boolean(), keyword()) ::
  {:ok, Formata.Schema.t()} | {:error, [Formata.Error.t(), ...]}
```

Compiles a JSON Schema document.

## Options

  * `:dialect` - `:draft7` or `:draft2020_12`
  * `:format_assertion` - assert `format` (default `false`)
  * `:content_assertion` - assert `contentEncoding`/`contentMediaType`/`contentSchema`
    (default `false`)
  * `:loader` - `(uri -> {:ok, schema} | {:error, term})` for remote references
    and custom meta-schemas
  * `:base_uri` - base URI for resolving relative references

---

*Consult [api-reference.md](api-reference.md) for complete listing*
