2026-09-17 · 8 min read
- json-schema
- validation
- api-design
JSON Schema object validation becomes subtle when a contract combines reusable subschemas. additionalProperties controls names not matched by keywords in the same schema object, which can make a closed base schema reject properties declared later through composition.
Newer dialects provide unevaluatedProperties, which can apply after relevant subschemas have evaluated instance properties. It is not a simple spelling replacement: the result depends on successful branches, references, annotations, and dialect support.
Declare the dialect and validator contract
Start every portable schema with an intentional $schema URI and record the production validator and supported vocabularies. A validator configured for an older draft may ignore, reject, or misinterpret newer keywords.
- Pin validator versions in reproducible builds.
- Fail clearly on unsupported dialects or required vocabularies.
- Resolve $id and $ref against defined base URIs.
- Test generated code separately from schema validation.
Understand evaluated-property flow
Properties can be evaluated through properties, patternProperties, additionalProperties, and applicable composed or conditional subschemas. unevaluatedProperties then constrains names that remain unevaluated according to the selected dialect.
Annotations from unsuccessful anyOf or oneOf alternatives do not automatically make their properties valid. Reduce confusing failures to branch-by-branch results before reading the final closure error.
Design extension points deliberately
Use additionalProperties when one schema object owns the complete property vocabulary. Use unevaluatedProperties when closure belongs around a composition whose supported branches contribute properties.
If third parties may extend an object, define a namespace, pattern, extension object, or permissive boundary explicitly. Accidental openness and accidental closure both create compatibility problems.
Build a schema conformance matrix
Use Flashman's JSON formatter for schemas and fixtures, URL tool for identifiers, diff for validator results, case converter for property-name variants, and hash for stable public fixtures.
Test allOf, anyOf, oneOf, conditionals, dependent schemas, nested objects, pattern properties, local and remote references, failing alternatives, unknown names, dialect upgrades, validator options, bundled schemas, and generated client payloads.