Skip to content

Reverse "contains" <-> "minContains"/"maxContains" dependency #1312

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 2 commits into from
Oct 8, 2022
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
76 changes: 59 additions & 17 deletions jsonschema-core.xml
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@
<xref target="schema-document">schema object</xref>.
</t>
</section>
<section title="Default Behaviors">
<section title="Default Behaviors" anchor="default-behaviors">
<t>
A missing keyword MUST NOT produce a false assertion result, MUST
NOT produce annotation results, and MUST NOT cause any other schema
Expand Down Expand Up @@ -2122,7 +2122,7 @@
</t>
<t>
"contains", whose behavior is affected by the presence and value of
"minContains", in the Validation vocabulary
"minContains"
</t>
</list>
</t>
Expand Down Expand Up @@ -2502,23 +2502,65 @@
</section>

<section title="Other Keywords for Applying Subschemas">
<section title="maxContains">
<t>
The value of this keyword MUST be a non-negative integer.
</t>
<t>
This keyword modifies the behavior of "contains" within the same schema object,
as described below in the section for that keyword.
</t>
<t>
Validation MUST always succeed against this keyword.
The value of this keyword is used as its annotation result.
</t>
</section>

<section title="minContains">
<t>
The value of this keyword MUST be a non-negative integer.
</t>
<t>
This keyword modifies the behavior of "contains" within the same schema object,
as described below in the section for that keyword.
</t>
<t>
Validation MUST always succeed against this keyword.
The value of this keyword is used as its annotation result.
</t>
<t> Per section <xref target="default-behaviors" format="counter"></xref>,
omitted keywords MUST NOT produce annotation results. However, as described
in the section for "contains", the absence of this keyword's annotation
causes "contains" to assume a minimum value of 1.
</t>
</section>

<section title="contains">
<t>
The value of this keyword MUST be a valid JSON Schema.
</t>
<t>
An array instance is valid against "contains" if at least one of
its elements is valid against the given schema,
except when "minContains" is present and has a value of 0, in which
case an array instance MUST be considered valid against the "contains" keyword,
even if none of its elements is valid against the given schema.
This keyword applies its subschema to array elements or object property values.
</t>
<t>
An instance is valid against "contains" if the number of elements or property
values that are valid against its subschema is with the inclusive range of
the minimum and (if any) maximum number of occurrences.
</t>
<t>
The maximum number of occurrences is provided by the "maxContains" keyword
within the same schema object as "contains". If "maxContains" is absent,
the maximum number of occurrences MUST be unbounded.
</t>
<t>
An object instance is valid against "contains" if at least one of
its properties is valid against the given schema,
except when "minContains" is present and has a value of 0, in which
case an object instance MUST be considered valid against the "contains" keyword,
even if none of its property values is valid against the given schema.
The minimum number of occurrences is provided by the "minContains" keyword
within the same schema object as "contains". If "minContains" is absent,
the minimum number of occurrences MUST be 1.
</t>
<t>
Implementations MAY implement the dependency on "minContians" and
"maxContains" by inspecting their values rather than reading annotations
produced by those keywords.
</t>
<t>
This keyword produces an annotation value which is an array of the
Expand All @@ -2531,13 +2573,13 @@
</t>
<t>
This annotation affects the behavior of "unevaluatedItems" in the
Unevaluated vocabulary, and MAY also be used to implement the
"minContains" and "maxContains" keywords in the Validation vocabulary.
Unevaluated vocabulary.
</t>
<t>
The subschema MUST be applied to every array element even after the first
match has been found, in order to collect annotations for use by other
keywords. This is to ensure that all possible annotations are collected.
The subschema MUST be applied to every array element or object property
value even after the first match has been found, in order to collect
annotations for use by other keywords. This is to ensure that all possible
annotations are collected.
</t>
</section>
</section>
Expand Down
55 changes: 6 additions & 49 deletions jsonschema-validation.xml
Original file line number Diff line number Diff line change
Expand Up @@ -404,53 +404,6 @@
Omitting this keyword has the same behavior as a value of false.
</t>
</section>

<section title="maxContains">
<t>
The value of this keyword MUST be a non-negative integer.
</t>
<t>
If "contains" is not present within the same schema object,
then this keyword has no effect.
</t>
<t>
An instance array or object is valid against "maxContains" in two ways,
depending on the form of the annotation result of an adjacent
<xref target="json-schema">"contains"</xref> keyword. The first way is if
the annotation result is an array and the length of that array is less than
or equal to the "maxContains" value. The second way is if the annotation
result is a boolean "true" and the instance length (number of items or
properties) is less than or equal to the "maxContains" value.
</t>
</section>

<section title="minContains">
<t>
The value of this keyword MUST be a non-negative integer.
</t>
<t>
If "contains" is not present within the same schema object,
then this keyword has no effect.
</t>
<t>
An instance array or object is valid against "minContains" in two ways,
depending on the form of the annotation result of an adjacent
<xref target="json-schema">"contains"</xref> keyword. The first way is if
the annotation result is an array and the length of that array is greater
than or equal to the "minContains" value. The second way is if the
annotation result is a boolean "true" and the instance length (number of
items or properties) is greater than or equal to the "minContains" value.
</t>
<t>
A value of 0 is allowed, but is only useful for setting a range
of occurrences from 0 to the value of "maxContains". A value of
0 causes "minContains" and "contains" to always pass validation
(but validation can still fail against a "maxContains" keyword).
</t>
<t>
Omitting this keyword has the same behavior as a value of 1.
</t>
</section>
</section>

<section title="Validation Keywords for Objects">
Expand Down Expand Up @@ -1368,8 +1321,8 @@
<section title="Keywords Moved from Validation to Core">
<t>
Several keywords have been moved from this document into the
<xref target="json-schema">Core Specification</xref> as of this draft, in some
cases with re-naming or other changes. This affects the following former
<xref target="json-schema">Core Specification</xref> starting with draft 2019-09,
in some cases with re-naming or other changes. This affects the following former
validation keywords:
<list style="hanging">
<t hangText='"definitions"'>
Expand All @@ -1393,6 +1346,10 @@
For this reason, they are better defined as a generic mechanism on which
validation, hyper-schema, and extension vocabularies can all be based.
</t>
<t hangText='"maxContains", "minContains"'>
These keywords modify the behavior of "contains", and are therefore
grouped with it in the applicator vocabulary.
</t>
<t hangText='"dependencies"'>
This keyword had two different modes of behavior, which made it
relatively challenging to implement and reason about.
Expand Down
9 changes: 9 additions & 0 deletions meta/applicator.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
"properties": {
"prefixItems": { "$ref": "#/$defs/schemaArray" },
"items": { "$dynamicRef": "#meta" },
"maxContains": { "$ref": "#/$defs/nonNegativeInteger" },
"minContains": {
"$ref": "#/$defs/nonNegativeInteger",
"default": 1
},
"contains": { "$dynamicRef": "#meta" },
"additionalProperties": { "$dynamicRef": "#meta" },
"properties": {
Expand Down Expand Up @@ -48,6 +53,10 @@
"not": { "$dynamicRef": "#meta" }
},
"$defs": {
"nonNegativeInteger": {
"type": "integer",
"minimum": 0
},
"schemaArray": {
"type": "array",
"minItems": 1,
Expand Down
5 changes: 0 additions & 5 deletions meta/validation.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,6 @@
"type": "boolean",
"default": false
},
"maxContains": { "$ref": "#/$defs/nonNegativeInteger" },
"minContains": {
"$ref": "#/$defs/nonNegativeInteger",
"default": 1
},
"maxProperties": { "$ref": "#/$defs/nonNegativeInteger" },
"minProperties": { "$ref": "#/$defs/nonNegativeIntegerDefault0" },
"required": { "$ref": "#/$defs/stringArray" },
Expand Down