In JSON Schema Draft 2020-12, unevaluatedProperties identifies valid keys by maintaining a set of 'evaluated' keys across the schema tree. Unlike Draft 7's additionalProperties, which only looks at the immediate object-level keys, unevaluatedProperties tracks whether a key has been validated by any sub-schema within a composition.
How Valid Keys are Identified in allOf
When a validator encounters an allOf block, it performs a union operation on all keys validated by each sub-schema. If sub-schema A validates property id and sub-schema B validates property name, both keys are marked as evaluated. If an unevaluatedProperties keyword is defined within or outside that allOf, it will only flag keys present in the instance that were not part of that union.
- Key Tracking: The validator maintains a state of keys that have been seen by
properties, patternProperties, additionalProperties, or defs.
- Composition Logic: In
allOf, the evaluation is additive. If any branch validates a key, that key is no longer "unevaluated" for the remainder of the validation process.
Migration Edge Cases and Failures
Transitioning from Draft 7 to 2020-12 often fails when developers rely on the restrictive nature of additionalProperties: false. Common issues include:
- The "Shadowing" Effect: In Draft 7, placing
additionalProperties: false inside an allOf branch only restricts keys not defined in that specific branch. In 2020-12, using unevaluatedProperties there might allow unexpected keys if a sibling branch in the same allOf hasn't explicitly validated them yet.
- Recursive Validation: If a schema uses
$ref to point to itself, the validator must correctly track the evaluation state across the recursive boundary. Some early implementations reset the evaluation set, causing unevaluatedProperties to incorrectly flag valid keys.
- PatternNames Interaction: Using
patternNames with complex regex can mark keys as evaluated. If the regex is too broad, it may "consume" keys that you intended for unevaluatedProperties to catch.
To ensure a safe migration, verify if your chosen validator fully supports the Draft 2020-12 specification's evaluation tracking, as many libraries still default to Draft 7-style key-level restrictions for compatibility.