Specification scope: Core with the Import, Units, and Validation companion specifications.

A telemetry project may need units and validation without alternate names or conditional composition. Copying the extended meta-schema would leave that project maintaining a private copy of definitions it does not intend to change.

Composition records the selection without a manually maintained copy of the parent definitions. Import processing copies the selected base definitions, selects the offered add-ins, and publishes the result under a new identifier. A processor resolves that URI to find the vocabulary permitted by the project.

Start with the extended meta-schema

The extended v0 meta-schema advertises optional bundles through $offers. A derived meta-schema references extended with $schema, imports its definitions, and selects bundles with $uses.

This complete custom meta-schema enables import because composition itself uses $import, then adds units and validation. It deliberately leaves out alternate names and conditional composition.

{
  "$schema": "https://json-structure.org/meta/extended/v0/#",
  "$id": "https://schemas.example.com/meta/telemetry/v0/#",
  "$import": "https://json-structure.org/meta/extended/v0/#",
  "$uses": [
    "JSONStructureImport",
    "JSONStructureUnits",
    "JSONStructureValidation"
  ],
  "$root": "#/definitions/SchemaDocument",
  "name": "TelemetrySchemaDialect"
}

This is the same composition form used by the published validation meta-schema: the new document imports the parent and reuses its SchemaDocument root. The selected add-ins augment the imported type model rather than requiring copied definitions.

$schema and $import do different jobs. $schema says which meta-schema checks this custom meta-schema. $import brings the parent’s definitions into the new document so #/definitions/SchemaDocument resolves locally after processing. Treating $schema as an implicit import would make the document depend on processor behavior it never declares.

Schemas name the dialect they obey

A consuming schema points $schema at the custom meta-schema. It also records the optional feature bundles it uses at its own root, following the add-in contract exposed through the composed meta-schema.

{
  "$schema": "https://schemas.example.com/meta/telemetry/v0/#",
  "$id": "https://schemas.example.com/telemetry/pressure-reading",
  "name": "PressureReadingSchema",
  "$uses": [
    "JSONStructureUnits",
    "JSONStructureValidation"
  ],
  "$root": "#/definitions/PressureReading",
  "definitions": {
    "PressureReading": {
      "name": "PressureReading",
      "type": "object",
      "properties": {
        "sensorId": {
          "type": "string",
          "pattern": "^P-[A-Z0-9]{6}$"
        },
        "pressure": {
          "type": "double",
          "unit": "kPa",
          "minimum": 80,
          "maximum": 120
        }
      },
      "required": ["sensorId", "pressure"],
      "additionalProperties": false
    }
  }
}

An application instance then points to that schema:

{
  "$schema": "https://schemas.example.com/telemetry/pressure-reading",
  "sensorId": "P-3A91F2",
  "pressure": 101.325
}

The schema has no altnames, oneOf, or if, and its declared dialect never admitted those vocabularies. An unknown keyword is therefore an error, not an invitation for a processor to guess whether it is an annotation, a typo, or a private extension.

The URI identifies the vocabulary

The custom meta-schema’s $id is not decorative branding. It gives the exact combination a stable identity. Schema registries can cache it, generators can select handlers from it, and validators can reject documents that use keywords outside it.

The URI identifies a narrower language than “extended JSON Structure.” Telemetry schemas may describe units and impose validation policy; they do not thereby pick up every other extension in the extended vocabulary.

The present drafts contain one inconsistency: core says $uses is instance-only while its own SchemaDocument meta-definition allows the property, and the published meta-schemas rely on root-level $uses. A schema or meta-schema is the instance at this layer, so the examples follow the shipped meta-schema behavior. Processors that interpret instance documents as application data only will reject the project’s published meta-schemas.

Fork the language when you intend to change its rules. Selecting vocabulary that the language already offers is composition, and giving that selection a URI makes it resolvable. A copied meta-schema would only disguise that simpler choice and create another document to keep in sync.