flashman
← All guides

JSON Schema array matching with contains

Model JSON array match counts with contains, minContains, and maxContains by declaring the dialect, separating length rules, and testing composition boundaries.

2026-09-20 · 8 min read

  • json-schema
  • validation
  • arrays

JSON Schema contains evaluates a subschema against array elements. Supporting dialects can combine it with minContains and maxContains to constrain how many array indexes match, enabling rules such as at least two administrators or no more than one primary contact.

Match cardinality is independent of total array length. minItems, maxItems, uniqueItems, items, and contains answer different questions and should remain separate in the schema and its error messages.

Pin the schema dialect

Declare the intended dialect with $schema and verify that every production validator supports it. Older drafts may understand contains while ignoring or rejecting minContains and maxContains, turning a precise rule into a weaker one.

  • Choose one dialect for producers, validators, and documentation.
  • Fail visibly on unsupported required vocabulary.
  • Record validator names and versions in conformance tests.
  • Avoid assuming editor warnings match runtime behavior.

Design the matching subschema

Make contains identify exactly the role or shape whose count matters. Broad anyOf branches, permissive object schemas, type coercion, and unanchored patterns can cause more elements to match than a reader expects.

An array element either contributes its index to the match set or does not for one contains evaluation. Satisfying several nested branches does not make the same index count several times.

Coordinate evaluation keywords

When using unevaluatedItems, understand how the chosen dialect and validator carry annotations from successful contains and composition evaluations. allOf, anyOf, if and then, and references can change which array locations are considered evaluated.

Keep complex policies readable by naming referenced subschemas and testing them independently before testing the complete composition. Prefer a clear schema over application code that tries to repair validator results afterward.

Publish a boundary fixture matrix

Create valid and invalid fixtures for zero matches, each exact boundary, one below and above, empty arrays, duplicates, ambiguous branches, malformed elements, and references. Assert both validity and a stable application-level error category.

Use Flashman's JSON formatter for schemas and instances, diff for boundary fixtures, regex tester for string constraints, number-base converter for numeric examples, and case converter for property-name drift. Re-run the matrix on validator and dialect upgrades.

Try these tools