You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Vert.x Json Schema provides an extendable and asynchronous implementation for https://json-schema.org/[Json Schema] specification.
5
5
You can use Json Schemas to validate every json structure. This module provides:
6
6
7
-
* Implementation of https://tools.ietf.org/html/draft-handrews-json-schema-validation-02[Json Schema draft2019-09]
8
-
* Implementation of https://tools.ietf.org/html/draft-handrews-json-schema-validation-01[Json Schema draft-7]
9
-
* Implementation of https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#schemaObject[OpenAPI 3 dialect].
10
-
* Non blocking `$ref` resolution and caching
11
-
* Lookup into the schema cache using {@link io.vertx.core.json.pointer.JsonPointer}
12
-
* Synchronous and asynchronous validation
13
-
* Ability to extend the validation tree adding new keywords and new format predicates
7
+
* Implementation of https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-validation-00[draft 2020-12]
8
+
* Implementation of https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-02[draft 2019-09]
9
+
* Implementation of https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01[draft 7]
10
+
* Implementation of https://datatracker.ietf.org/doc/html/draft-fge-json-schema-validation-00[draft 4]
11
+
* Dereferencing of `$ref` resolution and caching
14
12
* DSL to build schemas programmatically
15
13
16
14
== Using Vert.x Json Schema
@@ -39,35 +37,45 @@ dependencies {
39
37
40
38
== Concepts
41
39
42
-
=== Schema
40
+
=== JsonSchema
43
41
44
-
Each parsed schema is represented by a {@link io.vertx.json.schema.Schema} instance. A schema is a tree of {@link io.vertx.json.schema.common.Validator} objects,
45
-
where each one contains the necessary logic to perform the validation. The performed validation is _fail-fast_: as soon as a validation error is encountered, the validation fails without going further
42
+
Schemas can exist in 2 flavours:
46
43
47
-
=== SchemaParser & SchemaRouter
44
+
* JSON as in JSON natation
45
+
* Boolean as in `true/false`
48
46
49
-
The {@link io.vertx.json.schema.SchemaParser} is the component that parses the schemas from Json data structures to {@link io.vertx.json.schema.Schema} instances.
50
-
The {@link io.vertx.json.schema.SchemaRouter} is the component able to cache parsed schemas and resolve `$ref`.
51
-
Every time a new `$ref` is solved or a {@link io.vertx.json.schema.SchemaParser} parses a new schema, the new schema will be cached inside the corresponding {@link io.vertx.json.schema.SchemaRouter}.
52
-
The {@link io.vertx.json.schema.SchemaParser} can be extended to support custom keywords and formats.
47
+
The {@link io.vertx.json.schema.JsonSchema} interface allows both types to be handled without the constant check of the
48
+
underlying type.
53
49
54
-
The available {@link io.vertx.json.schema.SchemaParser} are:
50
+
=== SchemaRepository
55
51
56
-
* {@link io.vertx.json.schema.draft201909.Draft201909SchemaParser} for Json Schema Draft 2019-09
57
-
* {@link io.vertx.json.schema.draft7.Draft7SchemaParser} for Json Schema Draft 7
58
-
* {@link io.vertx.json.schema.openapi3.OpenAPI3SchemaParser} for OpenAPI 3 dialect
52
+
The {@link io.vertx.json.schema.SchemaRepository} holds {@link io.vertx.json.schema.JsonSchema} instances. It performs
53
+
dereferencing of schemas to speed up validation. The repository is a simple key store, this means that it does not allow
54
+
duplicate ids.
55
+
56
+
The repository can then create {@link io.vertx.json.schema.Validator} instances aware of all sub schemas in the
57
+
repository.
58
+
59
+
=== Validator
60
+
61
+
As the name implies the {@link io.vertx.json.schema.Validator} validates an object using a start schema. The output
62
+
format is dependent of the configuration.
59
63
60
64
== Parse a schema
61
65
62
-
To parse a schema you first need a schema router and a schema parser matching your schema _dialect_.
63
-
For example to instantiate a _draft 2019-09_ schema parser:
66
+
When working with multiple schemas or sub-schemas, it is recommended to use a `Repository`.
67
+
68
+
To parse a schema you first need a `JsonSchema` and some initial configuration. Since schemas can contain references it
69
+
is required for the validator and repository to be aware of your application `baseUri`. This allows you to reference your
70
+
own schemas in other sub-schemas. For the purpose of dereferencing, you don't need to configure a draft.
64
71
65
72
[source,$lang]
66
73
----
67
74
{@link examples.JsonSchemaExamples#instantiate}
68
75
----
69
76
70
-
You can reuse `SchemaRouter` instance for different `SchemaParser` and you can parse different `Schema` with same `SchemaParser`.
77
+
You can use `JsonSchema` instances for different `Validator` and you can parse different `JsonSchema` with `JsonParser`
78
+
directly.
71
79
72
80
Now you can parse the schema:
73
81
@@ -76,123 +84,31 @@ Now you can parse the schema:
76
84
{@link examples.JsonSchemaExamples#parse}
77
85
----
78
86
79
-
When you parse a schema you must provide the **schema pointer**, a pointer that identifies the location of the schema.
80
-
If you don't have any schema pointer `SchemaParser` will generate one for you:
81
-
82
-
[source,$lang]
83
-
----
84
-
{@link examples.JsonSchemaExamples#parseNoId}
85
-
----
86
-
87
87
[IMPORTANT]
88
88
====
89
-
Remember that the schema pointer is required to reference this schema later using Json Schema `$ref`
90
-
and to resolve relative references. If you load a schema from filesystem and you use relative references, **provide the correct pointer** or the
91
-
`SchemaRouter` won't be able to resolve the local filesystem `$ref`.
89
+
Remember that for security reasons, this module will not attempt to download any referenced sub-schema. All required
90
+
sub-schemas should be provided to a repository object.
92
91
====
93
92
94
93
== Validate
95
94
95
+
Given the dynamic nature of json-schema and the conditional `if-then-else` it is not possible to validate in a streaming
96
+
scenario. Validation is for this reason a blocking operation. If you are aware that validation will be a very expensive
97
+
process, then it is advisable to run the validation on a dedicated thread pool or using `executeBlocking`.
96
98
A schema could have two states:
97
99
98
-
* Synchronous: The validators tree can provide a synchronous validation. You can validate your json both using {@link io.vertx.json.schema.Schema#validateSync(Object)} and {@link io.vertx.json.schema.Schema#validateAsync(Object)}
99
-
* Asynchronous: One or more branches of the validator tree requires an asynchronous validation. You must use {@link io.vertx.json.schema.Schema#validateAsync(Object)} to validate your json. If you use {@link io.vertx.json.schema.Schema#validateSync(Object)} it will throw a {@link io.vertx.json.schema.NoSyncValidationException}
100
-
101
-
To validate a schema in an asynchronous state:
102
-
103
-
[source,$lang]
104
-
----
105
-
{@link examples.JsonSchemaExamples#validateAsync}
106
-
----
107
-
108
-
To validate a schema in a synchronous state:
100
+
To validate a schema:
109
101
110
102
[source,$lang]
111
103
----
112
-
{@link examples.JsonSchemaExamples#validateSync}
104
+
{@link examples.JsonSchemaExamples#validate}
113
105
----
114
106
115
-
To check the schema state you can use method {@link io.vertx.json.schema.Schema#isSync()}.
116
-
The schema can mutate the state in time, e.g. if you have a schema that is asynchronous because of a `$ref`,
117
-
after the first validation the external schema is cached and the schema will switch to synchronous state.
118
-
119
-
[NOTE]
120
-
====
121
-
If you use {@link io.vertx.json.schema.Schema#validateAsync(Object)} while the schema is in a synchronous state,
122
-
the schema will validate synchronously wrapping the result in the returned `Future`, avoiding unnecessary async computations and memory usage
123
-
====
124
-
125
-
== Adding custom formats
126
-
127
-
You can add custom formats to use with validation keyword `format` before parsing the schemas:
128
-
129
-
[source,$lang]
130
-
----
131
-
{@link examples.JsonSchemaExamples#customFormat}
132
-
----
133
-
134
-
== Adding custom keywords
135
-
136
-
For every new keyword type you want to provide, you must implement {@link io.vertx.json.schema.common.ValidatorFactory}
137
-
and provide an instance to `SchemaParser` using {@link io.vertx.json.schema.SchemaParser#withValidatorFactory(ValidatorFactory)}.
138
-
When parsing happens, the `SchemaParser` calls {@link io.vertx.json.schema.common.ValidatorFactory#canConsumeSchema(JsonObject)} for each registered factory.
139
-
If the factory can consume the schema, then the method {@link io.vertx.json.schema.common.ValidatorFactory#createValidator(JsonObject, JsonPointer, SchemaParserInternal, MutableStateValidator)}
140
-
is called. This method returns an instance of {@link io.vertx.json.schema.common.Validator}, that represents the object that will perform the validation.
141
-
If something goes wrong during `Validator` creation, a {@link io.vertx.json.schema.SchemaException} should be thrown
142
-
143
-
You can add custom keywords of three types:
144
-
145
-
* Keywords that always validate the input synchronously
146
-
* Keywords that always validate the input asynchronously
147
-
* Keywords with mutable state
148
-
149
-
=== Synchronous keywords
150
-
151
-
Synchronous validators must implement the interface {@link io.vertx.json.schema.common.SyncValidator}.
152
-
In the example below I add a keyword that checks if the number of properties in a json object is a multiple of a provided number:
107
+
== Custom formats
153
108
154
-
[source,$lang]
155
-
----
156
-
{@link examples.PropertiesMultipleOfValidator}
157
-
----
158
-
159
-
After we defined the keyword validator we can define the factory:
0 commit comments