JSON files and payloads are durable contracts when they cross process, language, repository, UI, or release boundaries. The standard separates payload identity from validation-schema identity so projects can use strict schemas without making every consumer brittle.
Durable JSON object payloads should carry root type and
version fields. This is the preferred identity form for data
models consumed as Python objects, JavaScript objects, service payloads,
saved app state, interchange records, and other cross-language contracts.
Version values may use hardware-style stepping such as a0,
a1, or b0 when that matches the project release
vocabulary.
{
"type": "wn.pcb.part",
"version": "a0",
"refdes": "U1"
}
Nested variant records should use kind when the parent object
already establishes the contract type and version. This keeps tagged unions
stable for Python, JavaScript, and schema validators without repeating the
root payload identity on every child object.
A root schema field is allowed for config-like files, request
envelopes, status files, package-local manifests, and compatibility inputs
where consumers historically identify the file format by a single schema
name. New schema-labeled formats must document the schema name, accepted
versions or stepping rules, and the JSON Schema artifact that validates the
file. Existing schema-root manifests may remain compatibility
inputs; new cross-language model objects should prefer root
type plus version.
Every governed JSON object that can be validated should have a real JSON
Schema artifact. Schema documents use JSON Schema vocabulary fields such as
$schema and $id; those fields identify the
validator artifact, not the payload object. Schema filenames and
$id values should be versioned so validators can pin the
accepted contract.
Structural contract checks should use a real JSON Schema validator, such as a Draft 2020-12 implementation, rather than reimplementing schema rules in project-specific audit code. JSON Schema owns required fields, field types, enums, array uniqueness, object shape, and additional-property policy. Repository audits own semantics the schema cannot know: path containment, referenced file existence, evidence disposition, generated-artifact policy, and project-specific migration allowances.
Validator diagnostics should be concise and path-addressed so a signoff
failure points to the exact payload field, for example
docs/contracts/example.json: commands[0].aliases must be array.
This is the standard pattern for reusable contract tooling; bespoke
validators should be limited to semantic checks that cannot be expressed in
JSON Schema.
Pydantic models are a good implementation mechanism for Python services,
local web servers, FastAPI routes, and Python-side validation. They do not
replace the source contract. When Pydantic exports JSON Schema, the exported
schema must be checked against the accepted contract docs and fixtures.
Discriminated unions should use the contract's kind field for
nested variants and preserve root type plus
version for durable payload objects.
Repositories may contain both styles during migration. Standards work
should first classify each JSON surface as durable object payload,
config-like file, package-local manifest, or compatibility input. The rule
is to document and validate each surface, not to churn downstream repos just
to rename schema to type plus
version. Repo-specific migrations require their own plans.