Skip to main content
Version: V2-Next

ADR 048: JSON Schema 2020-12 as the canonical modelling format

Date: 2026-07-15

Status: Accepted

Decision Makers: @derlinne, @luckey

Context​

Model Forge needs a single canonical format in which all Elements are modelled, without inventing a separate metamodel.

Decision​

All Elements are represented as JSON Schema 2020-12 documents. There is no separate class/slot/attribute metamodel.

Rationale​

  • JSON Schema is an open, widely adopted standard with an extensive toolchain (Ajv, networknt, json-schema-to-typescript).
  • Inheritance (allOf), polymorphism (oneOf) and compositional variants (anyOf) are native JSON Schema constructs.
  • $ref with URN values represents the reference graph directly in the schema — no secondary model needed.
  • The domain truth lives entirely in the schema document itself.

Constraints are native; extensions only annotate​

Per-attribute constraints are native JSON Schema keywords, not extensions: pattern, format, minLength/maxLength, minimum/maximum/exclusiveMinimum/multipleOf, enum/const, minItems/maxItems/uniqueItems, dependentRequired/dependentSchemas, if/then/else, unevaluatedProperties. Cross-field rules belong there as well — a verbose if/then beats a custom keyword, because validation, views and generators then handle it for free (see Data Modelling).

The x-* extension vocabulary annotates; it never constrains. An annotation may carry meaning JSON Schema cannot express, but it must not decide whether instance data is valid — a constraining x- keyword would produce documents that a standard validator accepts and Model Forge rejects. This holds for every annotation, present and future; the authoritative roster is CORE JSON Schema Extensions, not this ADR.

Annotations legitimately describe three different things, and none of them narrows the set of valid instances:

What it describesExampleWhy it is safe
the meaning of an instance valuex-core-ref — the string is a foreign keythe value is still just a string to a validator; the native pattern does the validating
the document's provenancex-xsd-source — which version carries the source XSDsays nothing about instance data at all
the model's presentationx-ui-position — editor canvas positiondesign-time metadata; never reaches an instance

x-core-ref (ADR 053) is the reference implementation of the first, hardest kind: the native keyword validates ("pattern": "^urn:"), the annotation carries the meaning (which artifact type the URN targets), and Model Forge adds a registry-aware existence check on import — strictly additional, never a substitute for validation. A new annotation of that kind follows the same three-part shape.

This is what bounds "no separate metamodel" in practice. It is still JSON Schema as long as:

  • a standard validator, given the document alone, can validate instances correctly — the domain truth stays in the document;
  • everything that must be enforced is native, or compiled down to native keywords;
  • attributes and types are expressed as properties and type, never in a parallel x- vocabulary such as x-attributes: [{name, type, constraints}].

A constraint JSON Schema genuinely cannot express (a checksum, membership in an external codelist) is an annotation plus an import-time check, with the accepted asymmetry that it is enforced only where Model Forge runs. Codelists have a native answer first: enum, or a $ref to an Enumeration Element.

See also​

  • JSON Schema Reference
  • Data Modelling: the construct-to-JSON-Schema mapping, including validation keywords
  • ADR 053: x-core-ref as a typed foreign-key annotation