unevaluatedProperties : Schema
unevaluatedProperties
SchemaValidates object properties that did not successfully validate against other standard object applicators.
Value | This keyword must be set to a valid JSON Schema |
---|---|
Kind | Applicator Annotation |
Applies To | Object |
Dialect | 2020-12 |
Changed In | None |
Introduced In | 2019-09 |
Vocabulary | Unevaluated |
Specification | https://json-schema.org/draft/2020-12/json-schema-core.html#section-11.3 |
Metaschema | https://json-schema.org/draft/2020-12/meta/unevaluated |
Official Tests | draft2020-12/unevaluatedProperties.json |
Default |
{}
|
Annotation | Array The set of instance property names validated by this keyword's subschema |
Affected By |
|
Affects | None |
Also See |
|
Validation with unevaluatedProperties
applies only to the child values of instance names that do not appear in the properties
, patternProperties
, additionalProperties
, or unevaluatedProperties
annotation results that apply to the instance location being validated. For all such properties, validation succeeds if the child instance validates against the unevaluatedProperties
schema.
Evaluation
It’s crucial to understand what evaluation means in this context.
unevaluatedProperties
considers annotations from properties
, patternProperties
, and additionalProperties
, both as adjacent keywords and in subschemas of adjacent keywords. Additionally, it is also affected by other unevaluatedProperties
in nested schemas (if present).
- The keywords
properties
,patternProperties
,additionalProperties
, andunevaluatedProperties
produce annotations for the properties they successfully validate against. - If any of these keywords generate an annotation for a particular property at the same instance location (independently of the schema location), that property is considered as evaluated.
- By definition, the
unevaluatedProperties
subschema is always applied afterproperties
,patternProperties
, andadditionalProperties
subschemas. - As its name implies,
unevaluatedProperties
applies to any object property that has not been previously evaluated.
Examples
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"unevaluatedProperties": true
}
{ "foo": "bar", "baz": 33 }
"John Doe"
{ "keyword": "/unevaluatedProperties", "instance": "", "value": [ "foo", "baz" ] }
- Here, no properties are defined in the above schema. Consequently, all properties in an object instance are considered unevaluated, and the
unevaluatedProperties
subschema applies to them. Since the subschema here is a boolean true, an instance with unevaluated properties, regardless of their value, is considered valid.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"unevaluatedProperties": false
}
{ "foo": "bar" }
[ "John", 46, false ]
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"foo": { "type": "string" }
},
"patternProperties": {
"^b": { "type": "number" }
},
"unevaluatedProperties": false
}
{ "foo": "foo", "bar": 36, "fooBar": false }
{ "foo": "foo", "bar": 36 }
{ "keyword": "/properties", "instance": "", "value": [ "foo" ] }
{ "keyword": "/patternProperties", "instance": "", "value": [ "bar" ] }
- For the first instace, the annotation result of
properties
is [ “foo” ], and the annotation result ofpatternProperties
is [ “bar” ]. However, the ‘fooBar’ property remains unevaluated, so theunevaluatedProperties
subschema applies to it. This subschema fails (as any instance against a false schema is always invalid), leading to the failure of the entire schema. - For the second instace, the annotation result of
properties
is [ “foo” ], and the annotation result ofpatternProperties
is [ “bar” ]. No properties remain unevaluated; hence, the instance is considered valid.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"foo": { "type": "string" }
},
"patternProperties": {
"^b": { "type": "number" }
},
"unevaluatedProperties": { "type": "boolean" }
}
{ "foo": "foo", "bar": 36 }
{ "keyword": "/properties", "instance": "", "value": [ "foo" ] }
{ "keyword": "/patternProperties", "instance": "", "value": [ "bar" ] }
{ "foo": "foo", "bar": 36, "fooBar": false }
{ "keyword": "/properties", "instance": "", "value": [ "foo" ] }
{ "keyword": "/patternProperties", "instance": "", "value": [ "bar" ] }
{ "keyword": "/unevaluatedProperties", "instance": "", "value": [ "fooBar" ] }
{ "foo": "foo", "bar": 36, "fooBar": "string" }
- For the first instance, there are no unevaluated properties.
- For the second instance, ‘fooBar’ is unevaluated, and the
unevaluatedProperties
subschema applies to it. ‘fooBar’ conforms to this subschema, and hence the instance is valid. The annotations produced by applicators are:properties
→ [ “foo” ],patternProperties
→ [ “bar” ], andunevaluatedProperties
→ [ “fooBar” ].
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"foo": { "type": "string" }
},
"allOf": [
{
"patternProperties": {
"^b": { "type": "number" }
}
}
],
"unevaluatedProperties": { "type": "boolean" }
}
{ "foo": "foo", "bar": 36, "fooBar": false }
{ "keyword": "/properties", "instance": "", "value": [ "foo" ] }
{ "keyword": "/allOf/0/patternProperties", "instance": "", "value": [ "foo" ] }
{ "keyword": "/unevaluatedProperties", "instance": "", "value": [ "fooBar" ] }
{ "foo": "foo", "bar": 36, "fooBar": "string" }
properties
is [ “foo” ], and the annotation result of nested patternProperties
is [ “bar” ]. The unevaluatedProperties
recognizes the annotations from properties
as well as patternProperties
(as it can see through adjacent and nested applicators as only the produced annotations matter, not the schema structure) and ensures that ‘fooBar’ remains unevaluated and its subschema applies to ‘fooBar’.
- The first instance passes as it conforms to the unevaluated subschema.
- The second instance fails as it does not conform to the unevaluated subschema.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"foo": { "type": "string" }
},
"allOf": [
{
"additionalProperties": true
}
],
"unevaluatedProperties": false
}
{ "foo": "foo" }
{ "keyword": "/properties", "instance": "", "value": [ "foo" ] },
{ "keyword": "/allOf/0/additionalProperties", "instance": "", "value": [ "foo" ] }
{ "foo": "foo", "bar": "bar" }
{ "keyword": "/properties", "instance": "", "value": [ "foo" ] }
{ "keyword": "/allOf/0/additionalProperties", "instance": "", "value": [ "foo", "bar" ] }
- In the first case, there are no unevaluated properties.
- In the second case, the nested
{ additionalProperties: true }
evaluated all the remaining properties. So there’s nothing left unevaluated.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"foo": { "type": "string" }
},
"$ref": "#/$defs/bar",
"unevaluatedProperties": false,
"$defs": {
"bar": {
"properties": {
"bar": { "type": "string" }
}
}
}
}
{ "foo": "foo", "bar": "bar" }
{ "keyword": "/properties", "instance": "", "value": [ "foo" ] }
{ "keyword": "/$ref/properties", "instance": "", "value": [ "bar" ] }
{ "foo": "foo", "bar": "bar", "baz": "baz" }
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"foo": { "type": "string" }
},
"allOf": [
{
"unevaluatedProperties": true
}
],
"unevaluatedProperties": false
}
{ "foo": "foo", "bar": 101 }
{ "keyword": "/properties", "instance": "", "value": [ "foo" ] }
{ "keyword": "/allOf/0/unevaluatedProperties", "instance": "", "value": [ "foo", "bar" ] }