Skip to content

Split "unevaluatedItems" and "unevaluatedProperties" into their own vocabulary. #981

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions hyper-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"$vocabulary": {
"https://json-schema.org/draft/2019-09/vocab/core": true,
"https://json-schema.org/draft/2019-09/vocab/applicator": true,
"https://json-schema.org/draft/2019-09/vocab/unevaluated": true,
"https://json-schema.org/draft/2019-09/vocab/validation": true,
"https://json-schema.org/draft/2019-09/vocab/meta-data": true,
"https://json-schema.org/draft/2019-09/vocab/format": false,
Expand Down
247 changes: 145 additions & 102 deletions jsonschema-core.xml
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,9 @@
results. They should not define additional constraints independent
of their subschemas.
</t>
<t>
Keywords within the same schema object are referred to as adjacent keywords.
</t>
<t>
Extension keywords, meaning those defined outside of this document
and its companions, are free to define other behaviors as well.
Expand Down Expand Up @@ -674,7 +677,8 @@
<section title="Keyword Interactions">
<t>
Keyword behavior MAY be defined in terms of the annotation results
of <xref target="root">subschemas</xref> and/or adjacent keywords.
of <xref target="root">subschemas</xref> and/or adjacent keywords
(keywords within the same schema object) and their subschemas.
Such keywords MUST NOT result in a circular dependency.
Keywords MAY modify their behavior based on the presence or absence
of another keyword in the same
Expand All @@ -700,15 +704,18 @@
<t>
Because annotation collection can add significant cost in terms of both
computation and memory, implementations MAY opt out of this feature.
Keywords known to an implementation to have assertion or applicator behavior
that depend on annotation results MUST then be treated as errors, unless
an alternate implementation producing the same behavior is available.
Keywords of this sort SHOULD describe reasonable alternate approaches
when appropriate. This approach is demonstrated by the
Keywords that are specified in terms of collected annotations SHOULD
describe reasonable alternate approaches when appropriate.
This approach is demonstrated by the
"<xref target="items" format="title"/>" and
"<xref target="additionalProperties" format="title"/>" keywords in this
document.
</t>
<t>
Note that when no such alternate approach is possible for a keyword,
implementations that do not support annotation collections will not
be able to support those keywords or vocabularies that contain them.
</t>
</section>
<section title="Identifiers" anchor="identifiers">
<t>
Expand Down Expand Up @@ -2346,52 +2353,6 @@
</t>
</section>

<section title="unevaluatedItems" anchor="unevaluatedItems">
<t>
The value of "unevaluatedItems" MUST be a valid JSON Schema.
</t>
<t>
The behavior of this keyword depends on the annotation results of
adjacent keywords that apply to the instance location being validated.
Specifically, the annotations from "prefixItems", "items", and "contains",
which can come from those keywords when they are adjacent to the
"unevaluatedItems" keyword. Those two annotations, as well as
"unevaluatedItems", can also result from any and all adjacent
<xref target="in-place">in-place applicator</xref> keywords.
This includes but is not limited to the in-place applicators
defined in this document.
</t>
<t>
If no relevant annotations are present, the "unevaluatedItems"
subschema MUST be applied to all locations in the array.
If a boolean true value is present from any of the relevant annotations,
"unevaluatedItems" MUST be ignored. Otherwise, the subschema
MUST be applied to any index greater than the largest annotation
value for "prefixItems", which does not appear in any annotation
value for "contains".
</t>
<t>
This means that "prefixItems", "items", "contains", and all in-place
applicators MUST be evaluated before this keyword can be evaluated.
Authors of extension keywords MUST NOT define an in-place applicator
that would need to be evaluated before this keyword.
</t>
<t>
If the "unevaluatedItems" subschema is applied to any
positions within the instance array, it produces an
annotation result of boolean true, analogous to the
behavior of "items".
</t>
<t>
Omitting this keyword has the same assertion behavior as
an empty schema.
</t>
<t>
Implementations that do not collect annotations MUST raise an error
upon encountering this keyword.
</t>
</section>

<section title="contains">
<t>
The value of this keyword MUST be a valid JSON Schema.
Expand Down Expand Up @@ -2499,56 +2460,6 @@
</t>
</section>

<section title="unevaluatedProperties" anchor="unevaluatedProperties">
<t>
The value of "unevaluatedProperties" MUST be a valid JSON Schema.
</t>
<t>
The behavior of this keyword depends on the annotation results of
adjacent keywords that apply to the instance location being validated.
Specifically, the annotations from "properties", "patternProperties",
and "additionalProperties", which can come from those keywords when
they are adjacent to the "unevaluatedProperties" keyword. Those
three annotations, as well as "unevaluatedProperties", can also
result from any and all adjacent
<xref target="in-place">in-place applicator</xref> keywords.
This includes but is not limited to the in-place applicators
defined in this document.
</t>
<t>
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.
</t>
<t>
For all such properties, validation succeeds if the child instance
validates against the "unevaluatedProperties" schema.
</t>
<t>
This means that "properties", "patternProperties", "additionalProperties",
and all in-place applicators MUST be evaluated before this keyword can
be evaluated. Authors of extension keywords MUST NOT define an in-place
applicator that would need to be evaluated before this keyword.
</t>
<t>
The annotation result of this keyword is the set of instance
property names validated by this keyword's subschema.
Annotation results for "unevaluatedProperties" keywords from
multiple schemas applied to the same instance location are combined
by taking the union of the sets.
</t>
<t>
Omitting this keyword has the same assertion behavior as
an empty schema.
</t>
<t>
Implementations that do not collect annotations MUST raise an error
upon encountering this keyword.
</t>
</section>

<section title="propertyNames">
<t>
The value of "propertyNames" MUST be a valid JSON Schema.
Expand All @@ -2566,6 +2477,138 @@
</section>
</section>

<section title="A Vocabulary for Unevaluated Locations">
<t>
The purpose of these keywords is to enable schema authors to apply
subschemas to array items or object properties that have not been
successfully evaluated against any dynamic-scope subschema of any
adjacent keywords.
</t>
<t>
These instance items or properties may have been unsuccessfully evaluated
against one or more adjacent keyword subschemas, such as when an assertion
in a branch of an "anyOf" fails. Such failed evaluations are not considered
to contribute to whether or not the item or property has been evaluated.
Only successful evaluations are considered.
Comment on lines +2488 to +2492
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been thinking about this section and its phrasing.
It's the first time in the whole document we mention "evaluation", and we don't really define what it means.

People (including myself previously) incorrectly assume that if a location has been evaluated (had something applied to it), then it counts as having been evaluated.

I'm going to riff some ideas...

We say here "successful evaluations", we mean if an application doesn't result in validation errors, and therefore the applied schema or keyword is correctly applicable to the instance location.

For example, if you had a schema...
anyOf [ { title> unicycle, props > wheels > const > 1 }, { title: bicycle, props > wheels > const > 2 } ]

If your instance was a unicycle, the first subschema item in the anyOf would be applied and successfully evaluated. Because it only has one wheel, we know it's a unicycle. It is not a bicycle, so that whole subschema is not successfully evaluated.

The instance is successfully evaluated as (or determined to be) a unicycle.

We can further justify this terminology by the fact that evaluation can be short-circuited, and therefore there's no expectation for a schema to be fully evaluated (although that would be a weak argument, and probably confuse things).


We need to clearly define what successful evaluation means, and what unsuccessful evaluation means, with justification (IMHO). I'm not currently convinced I can do that.

I'm happy for this to be a new issue in order to get this PR merged, but it would be essential to 2020-NN.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good point, and it should be made clear that these keywords really mean "unSucessfullyEvaluatedThing" rather than just "unEvaluatedThing".

</t>
<t>
Recall that adjacent keywords are keywords within the same schema object,
and that the dynamic-scope subschemas include reference targets as well as
lexical subschemas.
</t>
<t>
The behavior of these keywords depend on the annotation results of
adjacent keywords that apply to the instance location being validated.
</t>
<t>
Meta-schemas that do not use "$vocabulary" SHOULD be considered to
require this vocabulary as if its URI were present with a value of true.
</t>
<t>
The current URI for this vocabulary, known as the Unevaluated Applicator
vocabulary, is:
&lt;https://json-schema.org/draft/2019-09/vocab/unevaluated&gt;.
</t>
<t>
The current URI for the corresponding meta-schema is:
<eref target="https://json-schema.org/draft/2019-09/meta/unevaluated"/>.
</t>
<t>
Updated vocabulary and meta-schema URIs MAY be published between
specification drafts in order to correct errors. Implementations
SHOULD consider URIs dated after this specification draft and
before the next to indicate the same syntax and semantics
as those listed here.
</t>
<section title="unevaluatedItems" anchor="unevaluatedItems">
<t>
The value of "unevaluatedItems" MUST be a valid JSON Schema.
</t>
<t>
The behavior of this keyword depends on the annotation results of
adjacent keywords that apply to the instance location being validated.
Specifically, the annotations from "prefixItems", "items", and "contains",
which can come from those keywords when they are adjacent to the
"unevaluatedItems" keyword. Those two annotations, as well as
"unevaluatedItems", can also result from any and all adjacent
<xref target="in-place">in-place applicator</xref> keywords.
This includes but is not limited to the in-place applicators
defined in this document.
</t>
<t>
If no relevant annotations are present, the "unevaluatedItems"
subschema MUST be applied to all locations in the array.
If a boolean true value is present from any of the relevant annotations,
"unevaluatedItems" MUST be ignored. Otherwise, the subschema
MUST be applied to any index greater than the largest annotation
value for "prefixItems", which does not appear in any annotation
value for "contains".
</t>
<t>
This means that "prefixItems", "items", "contains", and all in-place
applicators MUST be evaluated before this keyword can be evaluated.
Authors of extension keywords MUST NOT define an in-place applicator
that would need to be evaluated before this keyword.
</t>
<t>
If the "unevaluatedItems" subschema is applied to any
positions within the instance array, it produces an
annotation result of boolean true, analogous to the
behavior of "items".
</t>
<t>
Omitting this keyword has the same assertion behavior as
an empty schema.
</t>
</section>

<section title="unevaluatedProperties" anchor="unevaluatedProperties">
<t>
The value of "unevaluatedProperties" MUST be a valid JSON Schema.
</t>
<t>
The behavior of this keyword depends on the annotation results of
adjacent keywords that apply to the instance location being validated.
Specifically, the annotations from "properties", "patternProperties",
and "additionalProperties", which can come from those keywords when
they are adjacent to the "unevaluatedProperties" keyword. Those
three annotations, as well as "unevaluatedProperties", can also
result from any and all adjacent
<xref target="in-place">in-place applicator</xref> keywords.
This includes but is not limited to the in-place applicators
defined in this document.
</t>
<t>
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.
</t>
<t>
For all such properties, validation succeeds if the child instance
validates against the "unevaluatedProperties" schema.
</t>
<t>
This means that "properties", "patternProperties", "additionalProperties",
and all in-place applicators MUST be evaluated before this keyword can
be evaluated. Authors of extension keywords MUST NOT define an in-place
applicator that would need to be evaluated before this keyword.
</t>
<t>
The annotation result of this keyword is the set of instance
property names validated by this keyword's subschema.
Annotation results for "unevaluatedProperties" keywords from
multiple schemas applied to the same instance location are combined
by taking the union of the sets.
</t>
<t>
Omitting this keyword has the same assertion behavior as
an empty schema.
</t>
</section>
</section>

<section title="Output Formatting" anchor="output">
<t>
JSON Schema is defined to be platform-independent. As such, to increase compatibility
Expand Down
2 changes: 0 additions & 2 deletions meta/applicator.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@
"properties": {
"prefixItems": { "$ref": "#/$defs/schemaArray" },
"items": { "$dynamicRef": "#meta" },
"unevaluatedItems": { "$dynamicRef": "#meta" },
"contains": { "$dynamicRef": "#meta" },
"additionalProperties": { "$dynamicRef": "#meta" },
"unevaluatedProperties": { "$dynamicRef": "#meta" },
"properties": {
"type": "object",
"additionalProperties": { "$dynamicRef": "#meta" },
Expand Down
15 changes: 15 additions & 0 deletions meta/unevaluated.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "https://json-schema.org/draft/2019-09/meta/unevaluated",
"$vocabulary": {
"https://json-schema.org/draft/2019-09/vocab/unevaluated": true
},
"$dynamicAnchor": "meta",

"title": "Unevaluated applicator vocabulary meta-schema",
"type": ["object", "boolean"],
"properties": {
"unevaluatedItems": { "$dynamicRef": "#meta" },
"unevaluatedProperties": { "$dynamicRef": "#meta" }
}
}
1 change: 1 addition & 0 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"$vocabulary": {
"https://json-schema.org/draft/2019-09/vocab/core": true,
"https://json-schema.org/draft/2019-09/vocab/applicator": true,
"https://json-schema.org/draft/2019-09/vocab/unevaluated": true,
"https://json-schema.org/draft/2019-09/vocab/validation": true,
"https://json-schema.org/draft/2019-09/vocab/meta-data": true,
"https://json-schema.org/draft/2019-09/vocab/format": false,
Expand Down