Skip to content

Commit a4fdba5

Browse files
committed
[WIP] Add full documentation for 2019-09
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent 637a898 commit a4fdba5

59 files changed

Lines changed: 4953 additions & 11 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

content/2019-09/applicator/additionalItems.markdown

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,105 @@ related:
3737
- vocabulary: applicator
3838
keyword: unevaluatedItems
3939
---
40+
41+
The `additionalItems` keyword restricts array instance items not described by
42+
the _sibling_ [`items`]({{< ref "2019-09/applicator/items" >}}) keyword (when
43+
[`items`]({{< ref "2019-09/applicator/items" >}}) is in array form), to
44+
validate against the given subschema. Whether this keyword was evaluated
45+
against any item of the array instance is reported using annotations.
46+
47+
{{<common-pitfall>}}This keyword **only** has an effect when the sibling
48+
[`items`]({{< ref "2019-09/applicator/items" >}}) keyword is set to an array of
49+
schemas. If [`items`]({{< ref "2019-09/applicator/items" >}}) is not present or is set to a schema (not an array),
50+
[`additionalItems`]({{< ref "2019-09/applicator/additionalitems" >}}) has no effect and is ignored. This is a common source of
51+
confusion.{{</common-pitfall>}}
52+
53+
{{<common-pitfall>}}This keyword does not prevent an array instance from being
54+
empty or having fewer items than the [`items`]({{< ref "2019-09/applicator/items" >}}) array. If needed, use the
55+
[`minItems`]({{< ref "2019-09/validation/minitems" >}}) to assert on the minimum
56+
bounds of the array.{{</common-pitfall>}}
57+
58+
{{<constraint-warning `array`>}}
59+
60+
## Examples
61+
62+
{{<schema `A schema that constrains array instances to start with a boolean item followed by a number item, with only string items allowed beyond that`>}}
63+
{
64+
"$schema": "https://json-schema.org/draft/2019-09/schema",
65+
"items": [ { "type": "boolean" }, { "type": "number" } ],
66+
"additionalItems": { "type": "string" }
67+
}
68+
{{</schema>}}
69+
70+
{{<instance-pass `An array value that consists of a boolean item followed by a number item is valid`>}}
71+
[ false, 35 ]
72+
{{</instance-pass>}}
73+
74+
{{<instance-annotation>}}
75+
{ "keyword": "/items", "instance": "", "value": true }
76+
{{</instance-annotation>}}
77+
78+
{{<instance-pass `An array value that consists of a boolean item followed by a number item and string items is valid`>}}
79+
[ false, 35, "foo", "bar" ]
80+
{{</instance-pass>}}
81+
82+
{{<instance-annotation>}}
83+
{ "keyword": "/items", "instance": "", "value": 1 }
84+
{ "keyword": "/additionalItems", "instance": "", "value": true }
85+
{{</instance-annotation>}}
86+
87+
{{<instance-fail `An array value that consists of a boolean item followed by a number item and non-string items is invalid`>}}
88+
[ false, 35, { "foo": "bar" } ]
89+
{{</instance-fail>}}
90+
91+
{{<instance-pass `An empty array value is valid`>}}
92+
[]
93+
{{</instance-pass>}}
94+
95+
{{<instance-pass `A non-array value is valid`>}}
96+
"Hello World"
97+
{{</instance-pass>}}
98+
99+
{{<schema `A schema that prevents additional items beyond the tuple`>}}
100+
{
101+
"$schema": "https://json-schema.org/draft/2019-09/schema",
102+
"items": [ { "type": "boolean" }, { "type": "number" } ],
103+
"additionalItems": false
104+
}
105+
{{</schema>}}
106+
107+
{{<instance-pass `An array value with exactly two items matching the tuple is valid`>}}
108+
[ false, 35 ]
109+
{{</instance-pass>}}
110+
111+
{{<instance-annotation>}}
112+
{ "keyword": "/items", "instance": "", "value": true }
113+
{{</instance-annotation>}}
114+
115+
{{<instance-fail `An array value with items beyond the tuple is invalid`>}}
116+
[ false, 35, "foo" ]
117+
{{</instance-fail>}}
118+
119+
{{<schema `A schema that demonstrates when this keyword has no effect`>}}
120+
{
121+
"$schema": "https://json-schema.org/draft/2019-09/schema",
122+
"items": { "type": "number" },
123+
"additionalItems": { "type": "string" }
124+
}
125+
{{</schema>}}
126+
127+
{{<instance-pass `An array value with only numbers is valid`>}}
128+
[ 1, 2, 3 ]
129+
{{</instance-pass>}}
130+
131+
{{<instance-annotation>}}
132+
{ "keyword": "/items", "instance": "", "value": true }
133+
{{</instance-annotation>}}
134+
135+
{{<instance-pass `An array value with numbers and strings is valid as the keyword is ignored`>}}
136+
[ 1, 2, "foo" ]
137+
{{</instance-pass>}}
138+
139+
{{<instance-annotation>}}
140+
{ "keyword": "/items", "instance": "", "value": true }
141+
{{</instance-annotation>}}

content/2019-09/applicator/additionalProperties.markdown

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ related:
4343

4444
The `additionalProperties` keyword restricts object instance properties not
4545
described by the _sibling_ [`properties`]({{< ref
46-
"2019-09/applicator/properties"
47-
>}}) and [`patternProperties`]({{< ref "2019-09/applicator/patternproperties"
46+
"2020-12/applicator/properties"
47+
>}}) and [`patternProperties`]({{< ref "2020-12/applicator/patternproperties"
4848
>}}) keywords (if any), to validate against the given subschema. Information
4949
about the properties that this keyword was evaluated for is reported using
5050
annotations.
5151

5252
{{<common-pitfall>}}The use of the [`properties`]({{< ref
53-
"2019-09/applicator/properties" >}}) keyword **does not prevent the presence of
53+
"2020-12/applicator/properties" >}}) keyword **does not prevent the presence of
5454
other properties** in the object instance and **does not enforce the presence
5555
of the declared properties**. In other words, additional data that is not
5656
explicitly prohibited is permitted by default. This is intended behaviour to
@@ -60,14 +60,14 @@ enable highly-expressive constraint-driven schemas.
6060
If you want to restrict instances to only contain the properties you declared,
6161
you must set this keyword to the boolean schema `false`, and if you want to
6262
enforce the presence of certain properties, you must use the [`required`]({{<
63-
ref "2019-09/validation/required" >}}) keyword accordingly.
63+
ref "2020-12/validation/required" >}}) keyword accordingly.
6464
{{</common-pitfall>}}
6565

6666
{{<learning-more>}}While the most common use of this keyword is setting it to
6767
the boolean schema `false` to prevent additional properties, it is possible to
6868
set it to a satisfiable schema. Doing this, while omitting the
69-
[`properties`]({{< ref "2019-09/applicator/properties" >}}) and
70-
[`patternProperties`]({{< ref "2019-09/applicator/patternproperties" >}})
69+
[`properties`]({{< ref "2020-12/applicator/properties" >}}) and
70+
[`patternProperties`]({{< ref "2020-12/applicator/patternproperties" >}})
7171
keywords, is an elegant way of describing how the value of every property in
7272
the object instance must look like independently of its
7373
name.{{</learning-more>}}

content/2019-09/applicator/allOf.markdown

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ operation, as instances are valid if they satisfy every constraint of every
3636
subschema (the intersection of the constraints).
3737

3838
{{<common-pitfall>}} Wrapping a single instance of the [`$ref`](../../core/ref)
39-
or [`$recursiveRef`](../../core/recursiveref) keyword in an `allOf` operator is
40-
an anti-pattern.
39+
or [`$dynamicRef`](../../core/dynamicref) keyword in an `allOf` operator is an
40+
anti-pattern.
4141

4242
This practice has historical roots. In JSON Schema [Draft 7](/draft7) and
4343
earlier versions, any subschema declaring the `$ref` keyword was considered to

content/2019-09/applicator/anyOf.markdown

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,153 @@ related:
2525
- vocabulary: applicator
2626
keyword: not
2727
---
28+
29+
The {{<link keyword="anyOf" vocabulary="applicator">}} keyword restricts
30+
instances to validate against _at least one_ (but potentially multiple) of the
31+
given subschemas. This keyword represents a [logical
32+
disjunction](https://en.wikipedia.org/wiki/Logical_disjunction) (OR) operation,
33+
as instances are valid if they satisfy the constraints of one or more
34+
subschemas (the union of the constraints).
35+
36+
{{<learning-more>}}Keep in mind that when collecting annotations, the JSON
37+
Schema implementation will need to exhaustively evaluate every subschema past
38+
the first match instead of short-circuiting validation, potentially introducing
39+
additional computational overhead.
40+
41+
For example, consider 3 subschemas where the instance validates against the
42+
first. When not collecting annotations, validation will stop after evaluating
43+
the first subschema. However, when collecting annotations, evaluation will have
44+
to proceed past the first subschema in case the others emit
45+
annotations.{{</learning-more>}}
46+
47+
This keyword is equivalent to the `||` operator found in most programming
48+
languages. For example:
49+
50+
```c
51+
bool valid = A || B || C;
52+
```
53+
54+
As a reference, the following boolean [truth
55+
table](https://en.wikipedia.org/wiki/Truth_table) considers the evaluation
56+
result of this keyword given 3 subschemas: A, B, and C.
57+
58+
<table class="table table-borderless border">
59+
<thead>
60+
<tr class="table-light">
61+
<th><code>anyOf</code></th>
62+
<th>Subschema A</th>
63+
<th>Subschema B</th>
64+
<th>Subschema C</th>
65+
</tr>
66+
</thead>
67+
<tbody>
68+
<tr class="table-danger">
69+
<td class="fw-bold"><i class="bi bi-x-circle-fill me-1"></i> Invalid</td>
70+
<td><i class="bi bi-x-circle"></i> Invalid</td>
71+
<td><i class="bi bi-x-circle"></i> Invalid</td>
72+
<td><i class="bi bi-x-circle"></i> Invalid</td>
73+
</tr>
74+
<tr class="table-success">
75+
<td class="fw-bold"><i class="bi bi-check-circle-fill me-1"></i> Valid</td>
76+
<td><i class="bi bi-x-circle"></i> Invalid</td>
77+
<td><i class="bi bi-x-circle"></i> Invalid</td>
78+
<td><i class="bi bi-check-circle"></i> Valid</td>
79+
</tr>
80+
<tr class="table-success">
81+
<td class="fw-bold"><i class="bi bi-check-circle-fill me-1"></i> Valid</td>
82+
<td><i class="bi bi-x-circle"></i> Invalid</td>
83+
<td><i class="bi bi-check-circle"></i> Valid</td>
84+
<td><i class="bi bi-x-circle"></i> Invalid</td>
85+
</tr>
86+
<tr class="table-success">
87+
<td class="fw-bold"><i class="bi bi-check-circle-fill me-1"></i> Valid</td>
88+
<td><i class="bi bi-x-circle"></i> Invalid</td>
89+
<td><i class="bi bi-check-circle"></i> Valid</td>
90+
<td><i class="bi bi-check-circle"></i> Valid</td>
91+
</tr>
92+
<tr class="table-success">
93+
<td class="fw-bold"><i class="bi bi-check-circle-fill me-1"></i> Valid</td>
94+
<td><i class="bi bi-check-circle"></i> Valid</td>
95+
<td><i class="bi bi-x-circle"></i> Invalid</td>
96+
<td><i class="bi bi-x-circle"></i> Invalid</td>
97+
</tr>
98+
<tr class="table-success">
99+
<td class="fw-bold"><i class="bi bi-check-circle-fill me-1"></i> Valid</td>
100+
<td><i class="bi bi-check-circle"></i> Valid</td>
101+
<td><i class="bi bi-x-circle"></i> Invalid</td>
102+
<td><i class="bi bi-check-circle"></i> Valid</td>
103+
</tr>
104+
<tr class="table-success">
105+
<td class="fw-bold"><i class="bi bi-check-circle-fill me-1"></i> Valid</td>
106+
<td><i class="bi bi-check-circle"></i> Valid</td>
107+
<td><i class="bi bi-check-circle"></i> Valid</td>
108+
<td><i class="bi bi-x-circle"></i> Invalid</td>
109+
</tr>
110+
<tr class="table-success">
111+
<td class="fw-bold"><i class="bi bi-check-circle-fill me-1"></i> Valid</td>
112+
<td><i class="bi bi-check-circle"></i> Valid</td>
113+
<td><i class="bi bi-check-circle"></i> Valid</td>
114+
<td><i class="bi bi-check-circle"></i> Valid</td>
115+
</tr>
116+
</tbody>
117+
</table>
118+
119+
## Examples
120+
121+
{{<schema `A schema that constrains object instances to require at least one of the given properties`>}}
122+
{
123+
"$schema": "https://json-schema.org/draft/2019-09/schema",
124+
"anyOf": [
125+
{ "required": [ "foo" ] },
126+
{ "required": [ "bar" ] }
127+
]
128+
}
129+
{{</schema>}}
130+
131+
{{<instance-pass `A value that only matches the first subschema is valid`>}}
132+
{ "foo": 1 }
133+
{{</instance-pass>}}
134+
135+
{{<instance-pass `A value that only matches the second subschema is valid`>}}
136+
{ "bar": 2 }
137+
{{</instance-pass>}}
138+
139+
{{<instance-pass `A value that matches every subschema is valid`>}}
140+
{ "foo": 1, "bar": 2 }
141+
{{</instance-pass>}}
142+
143+
{{<instance-fail `A value that does not match any of the subschemas is invalid`>}}
144+
{ "extra": 4 }
145+
{{</instance-fail>}}
146+
147+
{{<schema `A schema that constrains instances with logical disjunctions that emit annotations`>}}
148+
{
149+
"$schema": "https://json-schema.org/draft/2019-09/schema",
150+
"anyOf": [
151+
{ "title": "Branch #1", "type": "number" },
152+
{ "title": "Branch #2", "type": "string" },
153+
{ "title": "Branch #3", "type": "integer" }
154+
]
155+
}
156+
{{</schema>}}
157+
158+
{{<instance-pass `A value that only matches the first subschema receives the first annotation`>}}
159+
3.14
160+
{{</instance-pass>}}
161+
162+
{{<instance-annotation>}}
163+
{ "keyword": "/anyOf/0/title", "instance": "", "value": [ "Branch #1" ] }
164+
{{</instance-annotation>}}
165+
166+
{{<instance-pass `A value that matches two subschemas receives both annotations`>}}
167+
12345
168+
{{</instance-pass>}}
169+
170+
{{<instance-annotation>}}
171+
{ "keyword": "/anyOf/0/title", "instance": "", "value": [ "Branch #1" ] }
172+
{ "keyword": "/anyOf/2/title", "instance": "", "value": [ "Branch #3" ] }
173+
{{</instance-annotation>}}
174+
175+
{{<instance-fail `A value that does not match any of the subschemas is invalid and receives no annotations`>}}
176+
{ "foo": 1 }
177+
{{</instance-fail>}}

content/2019-09/applicator/contains.markdown

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,48 @@ related:
3131
- vocabulary: applicator
3232
keyword: unevaluatedItems
3333
---
34+
35+
The `contains` keyword restricts array instances to include one or more items
36+
(at any location of the array) that validate against the given subschema. The
37+
lower and upper bounds that are allowed to validate against the given subschema
38+
can be controlled using the [`minContains`]({{< ref
39+
"2019-09/validation/mincontains" >}}) and [`maxContains`]({{< ref
40+
"2019-09/validation/maxcontains" >}}) keywords.
41+
42+
{{<constraint-warning `array`>}}
43+
44+
## Examples
45+
46+
{{<schema `A schema that constrains array instances to contain at least one even number`>}}
47+
{
48+
"$schema": "https://json-schema.org/draft/2019-09/schema",
49+
"contains": {
50+
"type": "number",
51+
"multipleOf": 2
52+
}
53+
}
54+
{{</schema>}}
55+
56+
{{<instance-pass `An array value with one even number is valid`>}}
57+
[ "foo", 2, false, [ "bar" ], -5 ]
58+
{{</instance-pass>}}
59+
60+
{{<instance-pass `An array value with multiple even numbers is valid`>}}
61+
[ "foo", 2, false, 3, 4, [ "bar" ], -5, -3.0 ]
62+
{{</instance-pass>}}
63+
64+
{{<instance-pass `An array value that solely consists of even numbers is valid`>}}
65+
[ 2, 4, 6, 8, 10, 12 ]
66+
{{</instance-pass>}}
67+
68+
{{<instance-fail `An array value without any even number is invalid`>}}
69+
[ "foo", true ]
70+
{{</instance-fail>}}
71+
72+
{{<instance-fail `An empty array value is invalid`>}}
73+
[]
74+
{{</instance-fail>}}
75+
76+
{{<instance-pass `A non-array value is valid`>}}
77+
"Hello World"
78+
{{</instance-pass>}}

0 commit comments

Comments
 (0)