contains keyword validates that an array instance has a specified number of elements that match its schema. Unlike items, which validates element positions, contains validates based on matching count.
Syntax
contains value must be a valid JSON Schema. The minContains and maxContains values must be non-negative integers.
Behavior
An instance array is valid againstcontains if the number of elements that validate successfully against its schema falls within the specified range:
- Default minimum: 1 (if
minContainsis absent) - Default maximum: unbounded (if
maxContainsis absent) - The
containsschema is applied to each array element - Validation succeeds if the count of matching elements is within
[minContains, maxContains] - Produces an annotation with the array of matching element indices (or boolean
trueif all match) - Affects the behavior of
unevaluatedItems
Examples
Basic Contains
Require at least one string element:[1, 2, "hello"], ["a", "b"]Invalid:
[1, 2, 3], []
Exact Count
Require exactly 2 matching elements:[5, 15, 20, 8]Invalid:
[15] (too few), [15, 20, 25] (too many)
Range of Matches
Require between 1 and 3 matching elements:At Least N Matches
Require minimum count with no upper limit:["Apple", "banana", "Cherry", "Date", "eggplant"] (3+ capitalized)Invalid:
["Apple", "banana"] (only 1 capitalized)
At Most N Matches
Limit maximum occurrences:[1, 2, 3], [1, null, 2], [null, null]Invalid:
[null, null, null]
Note: minContains: 0 makes the constraint optional.
Complex Element Matching
Match elements with complex criteria:Tags Validation
Ensure specific tags are present:Search Results
Validate that search results contain relevant matches:Optional Contains
Make contains optional by settingminContains: 0:
[], ["[email protected]"], [1, 2, 3]Invalid:
["[email protected]", "[email protected]"] (too many emails)
Annotations
Thecontains keyword produces an annotation value which is:
- An array of zero-based indices for elements that validated successfully against the contains schema
- Boolean true if the schema validates successfully for every element
- The annotation is present even for empty arrays
["a", 1, "b", 2] with contains: {"type": "string"}:
Interaction with unevaluatedItems
Thecontains annotation affects unevaluatedItems by marking matching elements as evaluated. This must be considered when both keywords are present:
["hello"] (all items are strings, evaluated by contains)Invalid:
["hello", 123] (123 is unevaluated)
Short-Circuit Evaluation
Under most circumstances, evaluation can be short-circuited once the required count is met. However,contains must be applied to every element when:
unevaluatedItemsappears anywhere in the dynamic scope- Annotations are being collected
Comparison with items
| Keyword | Validates | Use Case |
|---|---|---|
items | All elements or positional elements | Homogeneous arrays, tuples |
contains | Count of elements matching schema | ”At least N items match” |
Common Use Cases
- Required elements: Ensure arrays contain specific types of elements
- Cardinality constraints: Limit occurrences of matching elements
- Search validation: Verify search results contain relevant matches
- Tag requirements: Ensure specific tags/labels are present
- Quality checks: Require minimum number of high-quality items
- Partial validation: Validate subset of array elements
Notes
- Default
minContainsis 1 when absent (not 0) - Explicitly set
minContains: 0to make matching optional maxContainswithoutminContainsmeans “at most N” matches (with default minimum of 1)- Empty arrays fail validation unless
minContains: 0 - The
containskeyword applies to arrays only - For non-array instances,
containsalways passes
Best Practices
- Use
containswhen you care about “how many match” not “what position” - Always specify both
minContainsandmaxContainsfor clarity - Set
minContains: 0explicitly when matches are optional - Combine with
itemswhen you need both positional and count-based validation - Use clear, specific schemas in
containsto avoid ambiguity - Consider performance: complex
containsschemas on large arrays can be expensive