= Vert.x Json Schema
:toc: left

Vert.x Json Schema provides an extendable and asynchronous implementation for https://json-schema.org/[Json Schema] specification.
You can use Json Schemas to validate every json structure. This module provides:

* Implementation of https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-validation-00[draft 2020-12]
* Implementation of https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-02[draft 2019-09]
* Implementation of https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01[draft 7]
* Implementation of https://datatracker.ietf.org/doc/html/draft-fge-json-schema-validation-00[draft 4]
* Dereferencing of `$ref` resolution and caching
* DSL to build schemas programmatically

== Using Vert.x Json Schema

To use Vert.x Json Schema, add the following dependency to the _dependencies_ section of your build descriptor:

* Maven (in your `pom.xml`):

[source,xml,subs="+attributes"]
----
<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-json-schema</artifactId>
  <version>${maven.version}</version>
</dependency>
----

* Gradle (in your `build.gradle` file):

[source,groovy,subs="+attributes"]
----
dependencies {
  compile 'io.vertx:vertx-json-schema:${maven.version}'
}
----

== Concepts

=== JsonSchema

Schemas can exist in 2 flavours:

* JSON as in JSON notation
* Boolean as in `true/false`

The {@link io.vertx.json.schema.JsonSchema} interface allows both types to be handled without the constant check of the
underlying type.

=== SchemaRepository

The {@link io.vertx.json.schema.SchemaRepository} holds {@link io.vertx.json.schema.JsonSchema} instances. It performs
dereferencing of schemas to speed up validation. The repository is a simple key store, this means that it does not allow
duplicate ids.

The repository can then create {@link io.vertx.json.schema.Validator} instances aware of all sub schemas in the
repository.

=== Validator

As the name implies the {@link io.vertx.json.schema.Validator} validates an object using a start schema. The output
format is dependent of the configuration.

== Parse a schema

When working with multiple schemas or sub-schemas, it is recommended to use a `Repository`.

To parse a schema you first need a `JsonSchema` and some initial configuration. Since schemas can contain references it
is required for the validator and repository to be aware of your application `baseUri`. This allows you to reference your
own schemas in other sub-schemas. For the purpose of dereferencing, you don't need to configure a draft.

[source,$lang]
----
{@link examples.JsonSchemaExamples#instantiate}
----

You can use `JsonSchema` instances for different `Validator` and you can parse different `JsonSchema` with `JsonParser`
directly.

Now you can parse the schema:

[source,$lang]
----
{@link examples.JsonSchemaExamples#parse}
----

[IMPORTANT]
====
Remember that for security reasons, this module will not attempt to download any referenced sub-schema. All required
sub-schemas should be provided to a repository object.
====

== Validate

Given the dynamic nature of json-schema and the conditional `if-then-else` it is not possible to validate in a streaming
scenario. Validation is for this reason a blocking operation. If you are aware that validation will be a very expensive
process, then it is advisable to run the validation on a dedicated thread pool or using `executeBlocking`.
A schema could have two states:

To validate a schema:

[source,$lang]
----
{@link examples.JsonSchemaExamples#validate}
----

== Custom formats

Adding custom formats is not allowed. This may sound like a limitation but it arises from the validation spec.
Validators are expected to assume unknown formats as valid input, delegating to the application business code the role
of validator for custom values.

== Building your schemas from code

If you want to build schemas from code, you can use the included DSL. Only Draft-7 is supported for this feature.

To start, add static imports for {@link io.vertx.json.schema.draft7.dsl.Schemas} and {@link io.vertx.json.schema.draft7.dsl.Keywords}

=== Creating the schema

Inside {@link io.vertx.json.schema.draft7.dsl.Schemas} there are static methods to create the schema:

[source,$lang]
----
{@link examples.JsonSchemaDslExamples#createSchema}
----

=== Using the keywords

For every schema you can add keywords built with {@link io.vertx.json.schema.draft7.dsl.Keywords} methods,
depending on the type of the schema:

[source,$lang]
----
{@link examples.JsonSchemaDslExamples#keywords}
----

=== Defining the schema structure

Depending on the schema you create, you can define a structure.

To create an object schema with some properties schemas and additional properties schema:

[source,$lang]
----
{@link examples.JsonSchemaDslExamples#createObject}
----

To create an array schema:

[source,$lang]
----
{@link examples.JsonSchemaDslExamples#createArray}
----

To create a tuple schema:

[source,$lang]
----
{@link examples.JsonSchemaDslExamples#createTuple}
----

=== `$ref` and aliases

To add a `$ref` schema you can use the {@link io.vertx.json.schema.common.dsl.Schemas#ref(JsonPointer)} method.
To assign an `$id` keyword to a schema, use {@link io.vertx.json.schema.common.dsl.SchemaBuilder#id(JsonPointer)}

You can also refer to schemas defined with this dsl using aliases. You can use {@link io.vertx.json.schema.common.dsl.SchemaBuilder#alias(String)} to assign an alias to
a schema. Then you can refer to a schema with an alias using {@link io.vertx.json.schema.common.dsl.Schemas#refToAlias(String)}:

[source,$lang]
----
{@link examples.JsonSchemaDslExamples#alias}
----

=== Using the schema

After you defined the schema, you can call {@link io.vertx.json.schema.common.dsl.SchemaBuilder#toJson()} to return the JSON notation of the schema:

[source,$lang]
----
{@link examples.JsonSchemaDslExamples#parse}
----
