Rule catalogue¶
A rule id such as OOLD-RT-08f2 names one normative statement (a MUST, MUST NOT, SHOULD,
SHOULD NOT or REQUIRED) from the OO-LD specification. Validators cite these ids in their
output, so a report that says a document fails OOLD-RT-08f2 should let you find exactly what that
means - this page is where that lookup lands. Ids are permanent and never reused: a rule that is
retired stays on this page, marked deprecated, so an id from an old report still resolves to
something.
How to read an entry¶
Every rule below lists the same four properties. Hovering over a property name in an entry repeats the explanation, so you do not have to come back here.
| Property | Meaning |
|---|---|
| Level | The RFC 2119 keyword this requirement is stated with. A validator reports a MUST-level finding as a failure and a SHOULD-level one as a warning, so the level decides severity rather than the check that found it. |
| Applies to | Who the requirement binds: a document, an implementation of OO-LD, or nobody in particular. This decides what is even able to enforce it. document - checkable by validating a schema or instance document; implementation - constrains an OO-LD implementation; needs a library conformance suite; advisory - guidance; nothing verifies it automatically. |
| Machine-checkable | Whether a validator could decide this rule by inspecting a document. It does not say the OO-LD validator enforces it today - oold rules list --unchecked reports that. |
| Since | The specification release this rule first appeared in. Ids are permanent and never reused, so this does not change once recorded. |
CNF - Serialization and conformance¶
OOLD-CNF-1120¶
- Level: MUST
- Applies to: document
- Machine-checkable: no
- Since: 1.0.0-rc.1
A conforming schema or instance must be interchangeable as JSON, canonicalized per RFC 8785.
JSON (RFC8259) is the canonical serialization: a conforming OO-LD schema or instance MUST be interchangeable as JSON, and the canonical form used for identity and integrity (for example content-hashing a versioned schema) is its JSON Canonicalization Scheme (RFC8785) serialization.
In context
The normative data model of OO-LD is the JSON data model shared by JSONSCHEMA and JSON-LD11. JSON (RFC8259) is the canonical serialization: a conforming OO-LD schema or instance MUST be interchangeable as JSON, and the canonical form used for identity and integrity (for example content-hashing a versioned schema) is its JSON Canonicalization Scheme (RFC8785) serialization.
See this rule in the specification (section: notation).
OOLD-CNF-22d3¶
- Level: MUST NOT
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A YAML serialization outside the JSON-compatible subset is not a conforming OO-LD serialization.
A YAML document outside this subset, including one relying on the features YAML-LD admits only in its Extended profile, MUST NOT be treated as a conforming OO-LD serialization.
In context
A document MAY additionally be authored or served as YAML, provided it stays within the JSON-compatible subset of YAML 1.2: no tags, anchors, aliases, or merge keys; a single document; and no implicit typing beyond what JSON expresses. Within this subset - which coincides with the Basic profile of YAML-LD - a YAML document maps one-to-one onto the JSON data model and converts to the canonical JSON without loss. A YAML document outside this subset, including one relying on the features YAML-LD admits only in its Extended profile, MUST NOT be treated as a conforming OO-LD serialization.
See this rule in the specification (section: notation).
OOLD-CNF-d71d¶
- Level: MUST
- Applies to: document
- Machine-checkable: no
- Since: 1.0.0-rc.1
Where a YAML form and its canonical JSON disagree, the JSON form is authoritative.
Where the two forms disagree, the JSON form MUST be treated as authoritative.
In context
Authors using YAML should be aware that YAML comments and implicit type coercions (for example the strings NO or 1.10 read as a boolean or a truncated number by some parsers) do not survive conversion to the canonical JSON. Where the two forms disagree, the JSON form MUST be treated as authoritative. Examples in this specification are shown as JSON, with an equivalent YAML rendering available under "View as YAML".
See this rule in the specification (section: notation).
SCH - Schema well-formedness and the meta-schema¶
OOLD-SCH-a9ee¶
- Level: MUST NOT
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
An OO-LD schema document must not be interpreted as a JSON-LD document.
OO-LD schema documents MUST NOT be interpreted as JSON-LD documents, because that would apply the schema's own @context to the schema itself and produce incorrect triples.
In context
- An OO-LD schema is consumed as a JSON-LD remote context (referenced by its URL from an instance's
@context), never as a JSON-LD document. OO-LD schema documents MUST NOT be interpreted as JSON-LD documents, because that would apply the schema's own@contextto the schema itself and produce incorrect triples.
See this rule in the specification (section: basic-concepts).
CMP - Composition, merge and override¶
OOLD-CMP-1d7e¶
- Level: MUST NOT
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
Reflected oneOf/anyOf branch contexts must not map the same keyword to different IRIs at the root.
The remote contexts of oneOf / anyOf branches MAY also be reflected into the @context, but they MUST NOT conflict at the root - they MUST NOT map the same keyword to different IRIs there.
In context
oneOf / anyOf. The remote contexts of oneOf / anyOf branches MAY also be reflected into the @context, but they MUST NOT conflict at the root - they MUST NOT map the same keyword to different IRIs there. A JSON-LD processor merges all listed contexts (most-recently-wins) and has no notion of which branch a given instance matched, so a root-level conflict would be decided by context order rather than by the branch the data conforms to.
See this rule in the specification (section: merging-remote-contexts).
OOLD-CMP-5266¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
An embedded object property should be reflected as that property's scoped JSON-LD context.
An embedded object reached under an object-valued property - one whose value is an object, directly (type: object) or as the items of an array (type: array), whether inlined or brought in by $ref - SHOULD be reflected as that property's scoped JSON-LD context, so its terms resolve only under that property and cannot conflict with a same-named term elsewhere.
In context
It MUST NOT be required to further process an OO-LD schema document in order to interpret it as a JSON-LD context. This implies that all occurrences of $ref in the schema are reflected in the JSON-LD context. An embedded object reached under an object-valued property - one whose value is an object, directly (type: object) or as the items of an array (type: array), whether inlined or brought in by $ref - SHOULD be reflected as that property's scoped JSON-LD context, so its terms resolve only under that property and cannot conflict with a same-named term elsewhere. That scoped context MAY reference the embedded schema remotely (by URL) or carry its terms inline. Where the embed graph is cyclic - a value type whose scoped context transitively references itself through remote schema files - JSON-LD processors cannot resolve the recursive remote contexts (see round-trip); breaking the cycle requires migrating the remote reference to a local (inline) context - inlining the term definitions so there is no remote hop to recurse - which MAY be flattened onto the root context as a shared vocabulary. Moving the remote reference to the root does not break the cycle; only replacing it with local definitions does. A $ref at the root level of the OO-LD schema is listed at the root of the JSON-LD context. (A scalar reference - a property whose value is an IRI string, not an embedded object - carries its target type in x-oold-range, not a $ref, and so contributes no scoped context.) In case of multiple $ref within allOf the corresponding remote contexts are merged into an array-valued @context (see merging-remote-contexts). For oneOf / anyOf this requires care to avoid conflicts. At any time the importing OO-LD schema MAY define its own or override the imported JSON-LD context.
See this rule in the specification (section: composition).
OOLD-CMP-53bf¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A schema's JSON Schema and JSON-LD base URIs should be aligned so a relative reference resolves the same under both.
Relative references resolve against the schema's $id (the JSON Schema base URI) and, on the JSON-LD side, against @base / the retrieval URL; these base URIs SHOULD be aligned so a relative reference resolves to the same absolute URL under both.
In context
Independent references and base URIs. A JSON Schema $ref and a JSON-LD @context entry are independent references: they MAY point to the same document (the typical OO-LD case, where one document is both a schema and a context) or to different documents - for example a plain JSON Schema referenced via $ref together with a separate remote @context that supplies the semantics. Relative references resolve against the schema's $id (the JSON Schema base URI) and, on the JSON-LD side, against @base / the retrieval URL; these base URIs SHOULD be aligned so a relative reference resolves to the same absolute URL under both. $id MUST NOT contain a non-empty fragment (JSONSCHEMA §8.2.1).
See this rule in the specification (section: merging-remote-contexts).
OOLD-CMP-6d7b¶
- Level: MUST
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
Branch-specific mappings for the same keyword must be scoped rather than placed at the root.
Where branches genuinely need different mappings for the same keyword, those mappings MUST be scoped with JSON-LD scoped contexts so each applies only where its branch applies, rather than placed at the root, since colliding root mappings are resolved by context order instead of by the branch the data conforms to: Type-scoped contexts when the branches are distinguished by @type. The
In context
Where branches genuinely need different mappings for the same keyword, those mappings MUST be scoped with JSON-LD scoped contexts so each applies only where its branch applies, rather than placed at the root, since colliding root mappings are resolved by context order instead of by the branch the data conforms to:
- Type-scoped contexts when the branches are distinguished by
@type. The
See this rule in the specification (section: merging-remote-contexts).
OOLD-CMP-a05a¶
- Level: MUST
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A scoped context that must apply only to the immediate node sets @propagate false; contexts in one array share it.
Where a referenced context should apply only to the immediate node, the schema MUST set "@propagate": false on that scoped context.
In context
Propagation (@propagate). A $ref inside a type: object property is reflected as a property-scoped context, which by default propagates into the whole subtree rooted at that property ("By default ... contexts propagate across node objects, other than for type-scoped contexts, which default to false"). Where a referenced context should apply only to the immediate node, the schema MUST set "@propagate": false on that scoped context.
See this rule in the specification (section: merging-remote-contexts).
OOLD-CMP-b926¶
- Level: MUST NOT
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A schema must be usable as a JSON-LD context with no further processing, so every $ref is reflected in the @context.
It MUST NOT be required to further process an OO-LD schema document in order to interpret it as a JSON-LD context.
In context
It MUST NOT be required to further process an OO-LD schema document in order to interpret it as a JSON-LD context. This implies that all occurrences of $ref in the schema are reflected in the JSON-LD context. An embedded object reached under an object-valued property - one whose value is an object, directly (type: object) or as the items of an array (type: array), whether inlined or brought in by $ref - SHOULD be reflected as that property's scoped JSON-LD context, so its terms resolve only under that property and cannot conflict with a same-named term elsewhere. That scoped context MAY reference the embedded schema remotely (by URL) or carry its terms inline. Where the embed graph is cyclic - a value type whose scoped context transitively references itself through remote schema files - JSON-LD processors cannot resolve the recursive remote contexts (see round-trip); breaking the cycle requires migrating the remote reference to a local (inline) context - inlining the term definitions so there is no remote hop to recurse - which MAY be flattened onto the root context as a shared vocabulary. Moving the remote reference to the root does not break the cycle; only replacing it with local definitions does. A $ref at the root level of the OO-LD schema is listed at the root of the JSON-LD context. (A scalar reference - a property whose value is an IRI string, not an embedded object - carries its target type in x-oold-range, not a $ref, and so contributes no scoped context.) In case of multiple $ref within allOf the corresponding remote contexts are merged into an array-valued @context (see merging-remote-contexts). For oneOf / anyOf this requires care to avoid conflicts. At any time the importing OO-LD schema MAY define its own or override the imported JSON-LD context.
See this rule in the specification (section: composition).
OOLD-CMP-dd2b¶
- Level: MUST NOT
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A schema $id must not contain a non-empty fragment.
$id MUST NOT contain a non-empty fragment (JSONSCHEMA §8.2.1).
In context
Independent references and base URIs. A JSON Schema $ref and a JSON-LD @context entry are independent references: they MAY point to the same document (the typical OO-LD case, where one document is both a schema and a context) or to different documents - for example a plain JSON Schema referenced via $ref together with a separate remote @context that supplies the semantics. Relative references resolve against the schema's $id (the JSON Schema base URI) and, on the JSON-LD side, against @base / the retrieval URL; these base URIs SHOULD be aligned so a relative reference resolves to the same absolute URL under both. $id MUST NOT contain a non-empty fragment (JSONSCHEMA §8.2.1).
See this rule in the specification (section: merging-remote-contexts).
OOLD-CMP-e4a3¶
- Level: MUST
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A schema with multiple $refs must list their remote contexts as an array, in allOf order.
By the reflection rule above, the schema's own @context MUST list those remote contexts as an array, in the same order as the allOf members, so the schema stays usable as a context without further processing.
In context
Multiple $ref (e.g. in allOf) each correspond to a remote context. By the reflection rule above, the schema's own @context MUST list those remote contexts as an array, in the same order as the allOf members, so the schema stays usable as a context without further processing. A JSON-LD processor then resolves that array in order, later entries overriding earlier ones - duplicate context terms are overridden using a most-recently-defined-wins mechanism (JSONLD11-API, Context Processing Algorithm). The schema MAY append its own context object as the last array entry to override an inherited term. The single-context @import keyword is an alternative only when exactly one remote context is wrapped and locally modified (it cannot contain a nested @import), so the array form is used for the multi-$ref case.
See this rule in the specification (section: merging-remote-contexts).
OOLD-CMP-f3c7¶
- Level: MUST NOT
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
Composition is narrow-only: a derived schema may restrict a constraint but must not relax it.
For assertion-bearing keywords the resolved view additionally honors narrow-only composition: a derived schema MAY restrict a constraint but MUST NOT relax it, matching how code generators let a subclass tighten - never loosen - a superclass property's validation.
In context
When such a merge is required, OO-LD resolves the allOf chain by applying JSON Merge Patch (RFC7396) semantics: keyed by object member, most-recently-defined (most-derived) wins, and a null value removes a key. For the @context this coincides with JSON-LD's own override rule. For assertion-bearing keywords the resolved view additionally honors narrow-only composition: a derived schema MAY restrict a constraint but MUST NOT relax it, matching how code generators let a subclass tighten - never loosen - a superclass property's validation.
See this rule in the specification (section: merge-and-override-model).
INS - Instances: $schema, identity, semantic type, value forms¶
OOLD-INS-1d33¶
- Level: MUST
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
An exported identifiable entity must carry an IRI.
An implementation MAY use a non-IRI identifier internally, but when it exports an identifiable entity (to JSON-LD / RDF) it MUST assign an @id (or the aliased id).
In context
An implementation MAY use a non-IRI identifier internally, but when it exports an identifiable entity (to JSON-LD / RDF) it MUST assign an @id (or the aliased id). The @id SHOULD be resolvable, and it is RECOMMENDED to mint it from an autogenerated UUID - mirroring the schema's x-oold-uuid - e.g. https://example.org/a1b2c3d4-1234-....
See this rule in the specification (section: identity).
OOLD-INS-1df7¶
- Level: MUST NOT
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
Under the value-form pattern a reference is written as an object and its term must not carry @type.
References are written as objects, and the term MUST NOT carry @type.
In context
- Value-form - a single plain term (no
@type: "@id"); the value shape alone disambiguates: a bare scalar is a literal,{ "id": ... }is a reference, a typed object is embedded. References are written as objects, and the term MUST NOT carry@type.
See this rule in the specification (section: value-forms).
OOLD-INS-27aa¶
- Level: SHOULD NOT
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
A consumer should not blindly trust the schema an instance declares for itself.
JSON Schema deliberately does not standardize $schema on instances, partly over a self-validation concern: a consumer SHOULD NOT blindly trust the schema an instance declares for itself (a crafted instance could point at a permissive schema) and remains responsible for validating against a schema it trusts.
In context
@context already provides a JSON-LD-native link to the schema (resolution case 2 above), so $schema is kept primarily for compatibility with the widespread editor and CI convention, not as a second authoritative mechanism. JSON Schema deliberately does not standardize $schema on instances, partly over a self-validation concern: a consumer SHOULD NOT blindly trust the schema an instance declares for itself (a crafted instance could point at a permissive schema) and remains responsible for validating against a schema it trusts.
See this rule in the specification (section: referencing-schema).
OOLD-INS-2b3f¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
Schemas should expose @id through an aliased id property.
To keep instance keys variable-name-friendly, schemas SHOULD expose @id through an aliased id property (as with type -> @type):
See this rule in the specification (section: identity).
OOLD-INS-2e5d¶
- Level: MUST NOT
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A property whose range includes free text must not use @type @id.
A property whose range is references only therefore uses @type: "@id" and MAY be written as a bare IRI string; a property whose range includes free text MUST NOT use @type: "@id".
In context
A single @context term cannot interpret a bare string as both a literal and an IRI: @type: "@id" coerces every string value to an IRI (so free text becomes an - often invalid, then dropped - IRI), while a plain term keeps every string a literal. A property whose range is references only therefore uses @type: "@id" and MAY be written as a bare IRI string; a property whose range includes free text MUST NOT use @type: "@id".
See this rule in the specification (section: value-forms).
OOLD-INS-4b5c¶
- Level: MUST
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
An inline type must be consistent with the schema's x-oold-instance-rdf-type.
If an inline type is present it MUST be consistent with the schema's x-oold-instance-rdf-type.
In context
If an inline type is present it MUST be consistent with the schema's x-oold-instance-rdf-type. Note that @type alone lets a consumer locate the schema (case 3 above) only when one of the type IRIs resolves to an OO-LD schema.
See this rule in the specification (section: semantic-type).
OOLD-INS-559f¶
- Level: MUST
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
The nearest x-oold-instance-rdf-type declaration in an allOf chain replaces a base class's value rather than appending to it.
The nearest declaration in the allOf chain is authoritative and MUST replace a base class's value rather than append to it.
In context
Under composition, x-oold-instance-rdf-type follows the same most-derived-wins rule as the rest of the schema (see composition). The nearest declaration in the allOf chain is authoritative and MUST replace a base class's value rather than append to it. Superclass types are recoverable by ontology inference (rdfs:subClassOf) and so need not be materialized; a schema that wants a supertype carried in the data lists it explicitly (e.g. ["schema:Researcher", "schema:Person"]).
See this rule in the specification (section: semantic-type).
OOLD-INS-75c6¶
- Level: MUST
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
Tooling exporting an instance must materialize the schema-declared rdf:type(s) as @type.
Therefore, when OO-LD tooling exports an instance (to JSON-LD / RDF), it MUST materialize the declared rdf:type(s) as an @type on the instance, so that the type reaches RDF without access to the schema or to a type registry.
In context
These types live in the schema, not in the instance data, so a JSON-LD-only processor - which sees only the instance and its @context - cannot derive them. Therefore, when OO-LD tooling exports an instance (to JSON-LD / RDF), it MUST materialize the declared rdf:type(s) as an @type on the instance, so that the type reaches RDF without access to the schema or to a type registry.
See this rule in the specification (section: semantic-type).
OOLD-INS-9416¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
Instances should reference a versioned schema URL.
Instances SHOULD use a versioned schema URL so that it is unambiguous which schema version they conform to.
In context
The two SHOULD point at the same schema URL, so that the context an instance is read with and the schema it is validated against are the same document. Instances SHOULD use a versioned schema URL so that it is unambiguous which schema version they conform to.
See this rule in the specification (section: schema-instances).
OOLD-INS-ba9e¶
- Level: MUST
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A schema closing its objects must still permit the $schema and @context members.
Because an instance carries $schema and @context as ordinary members, an OO-LD schema that closes its objects with additionalProperties: false or unevaluatedProperties: false MUST permit these two members, or conforming instances would fail validation.
See this rule in the specification (section: referencing-schema).
OOLD-INS-cb1a¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
An instance's @context and $schema should point at the same schema URL.
The two SHOULD point at the same schema URL, so that the context an instance is read with and the schema it is validated against are the same document.
In context
The two SHOULD point at the same schema URL, so that the context an instance is read with and the schema it is validated against are the same document. Instances SHOULD use a versioned schema URL so that it is unambiguous which schema version they conform to.
See this rule in the specification (section: schema-instances).
OOLD-INS-cd80¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: no
- Since: 1.0.0-rc.1
An instance @id should be resolvable, and is recommended to be minted from an autogenerated UUID.
The @id SHOULD be resolvable, and it is RECOMMENDED to mint it from an autogenerated UUID - mirroring the schema's x-oold-uuid - e.g. https://example.org/a1b2c3d4-1234-....
In context
An implementation MAY use a non-IRI identifier internally, but when it exports an identifiable entity (to JSON-LD / RDF) it MUST assign an @id (or the aliased id). The @id SHOULD be resolvable, and it is RECOMMENDED to mint it from an autogenerated UUID - mirroring the schema's x-oold-uuid - e.g. https://example.org/a1b2c3d4-1234-....
See this rule in the specification (section: identity).
OOLD-INS-da1a¶
- Level: SHOULD
- Applies to: advisory
- Machine-checkable: no
- Since: 1.0.0-rc.1
A model ecosystem should adopt one of the two ambiguous-range patterns consistently.
For a property whose range mixes free text with references and/or embedded objects (for example Text | PostalAddress | Place), two patterns keep the instance round-trippable (see round-trip); a model ecosystem SHOULD adopt one of them consistently:
In context
For a property whose range mixes free text with references and/or embedded objects (for example Text | PostalAddress | Place), two patterns keep the instance round-trippable (see round-trip); a model ecosystem SHOULD adopt one of them consistently:
- Value-form - a single plain term (no
@type: "@id"); the value shape alone disambiguates: a bare scalar is a literal,{ "id": ... }is a reference, a typed object is embedded. References are written as objects, and the term MUST NOT carry@type. - Separate keys - a canonical term
pwith@type: "@id"(a bare IRI string reference, plus embedded objects via a scoped@context) and a companionp_textthat is a plain term for the literal.
See this rule in the specification (section: value-forms).
OOLD-INS-f010¶
- Level: MUST NOT
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
A consuming side must not be assumed to hold an rdf:type-to-schema registry; exports are self-sufficient.
An implementation MAY additionally maintain a registry mapping rdf:type IRIs to OO-LD schemas to resolve case 3, but such a registry MUST NOT be assumed to exist on the consuming side - so exports must be self-sufficient (see below).
See this rule in the specification (section: referencing-schema).
RT - Projection to RDF and round-trip safety¶
OOLD-RT-08f2¶
- Level: MUST
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A strictly array-typed property must declare @container @set or @list.
Because the reconstruction MUST re-validate, a property that is strictly an array (JSON Schema type: "array") MUST declare @container: "@set" (or "@list"): without it a single-element array returns as a scalar and violates the array type.
In context
- Multi-valued properties are set-valued in RDF: order is not preserved, duplicates are removed, and a single value compacts to a scalar. Because the reconstruction MUST re-validate, a property that is strictly an array (JSON Schema
type: "array") MUST declare@container: "@set"(or"@list"): without it a single-element array returns as a scalar and violates thearraytype. A property that also permits a scalar (ananyOf/oneOfof a literal and an array) MAY declare it for a stable array shape, but need not - the scalar form still validates, and a single value and a one-element array are JSON-LD-equivalent. Round-trip equality is set equality. A property SHOULD NOT declare@listunless the order of its values is significant, since ordering costs merge and query ergonomics.
See this rule in the specification (section: round-trip).
OOLD-RT-2028¶
- Level: SHOULD NOT
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A property should not declare @list unless the order of its values is significant.
A property SHOULD NOT declare @list unless the order of its values is significant, since ordering costs merge and query ergonomics.
In context
- Multi-valued properties are set-valued in RDF: order is not preserved, duplicates are removed, and a single value compacts to a scalar. Because the reconstruction MUST re-validate, a property that is strictly an array (JSON Schema
type: "array") MUST declare@container: "@set"(or"@list"): without it a single-element array returns as a scalar and violates thearraytype. A property that also permits a scalar (ananyOf/oneOfof a literal and an array) MAY declare it for a stable array shape, but need not - the scalar form still validates, and a single value and a one-element array are JSON-LD-equivalent. Round-trip equality is set equality. A property SHOULD NOT declare@listunless the order of its values is significant, since ordering costs merge and query ergonomics.
See this rule in the specification (section: round-trip).
OOLD-RT-a12c¶
- Level: MUST
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
An embedded object must carry an explicit type where the scoped context is type-scoped or the reconstruction frame matches on @type.
The embedded object MUST carry an explicit type where the property's scoped @context is type-scoped - keyed by the value's @type to distinguish several embedded types (or to stamp the node's rdf:type) - or where the frame used to reconstruct it matches on @type, as a frame derived from the schema's class type does (see framing).
In context
- Embedded objects are flattened in RDF, and compaction does not re-nest a flat graph, so reconstructing the tree requires Framing - the frame can be as small as
{ "<property>": {} }. The embedded object MUST carry an explicittypewhere the property's scoped@contextis type-scoped - keyed by the value's@typeto distinguish several embedded types (or to stamp the node'srdf:type) - or where the frame used to reconstruct it matches on@type, as a frame derived from the schema's class type does (see framing). A flat scoped context reconstructed through a property-matching frame needs none. Where required, tooling materializes the type on export (see semantic-type).
See this rule in the specification (section: round-trip).
OOLD-RT-ad63¶
- Level: SHOULD NOT
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A numeric property should not be coerced to a narrower datatype unless the exact RDF datatype matters.
A numeric property SHOULD NOT be coerced to a narrower datatype, and its values SHOULD be left as native JSON numbers, unless the exact RDF datatype matters.
In context
Datatypes JSON-LD does not produce by default are the ones to declare with @type: the date/time family (xsd:date, xsd:dateTime, xsd:time, xsd:duration), xsd:anyURI, and every numeric refinement outside the two native ones (xsd:float, xsd:decimal, xsd:long, xsd:int, xsd:unsignedByte, ...). These stay explicit on the literal through the round-trip and compact back onto the term, but JSON has no native syntax for them, so their value is carried as a JSON string. The consequence is worth stating plainly: a JSON-native number can only ever be xsd:integer or xsd:double; any narrower or more specific numeric datatype is reached by writing the value as a string under an @type coercion (a bare JSON number under, say, @type: "xsd:float" keeps the term but comes back as its canonical string form). A numeric property SHOULD NOT be coerced to a narrower datatype, and its values SHOULD be left as native JSON numbers, unless the exact RDF datatype matters.
See this rule in the specification (section: value-forms).
OOLD-RT-d376¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
The embed graph formed by scoped @contexts should be acyclic.
These scoped contexts form an embed graph between schemas, and that graph SHOULD be acyclic: model a property whose value is an independent entity, or whose type would close an embed cycle (a type embedding itself, or two types embedding each other), as a reference - @type: "@id" plus x-oold-range, with no scoped @context - rather than an embed.
In context
An embedded object is mapped by a scoped @context on its property (referencing the embedded type's own context). These scoped contexts form an embed graph between schemas, and that graph SHOULD be acyclic: model a property whose value is an independent entity, or whose type would close an embed cycle (a type embedding itself, or two types embedding each other), as a reference - @type: "@id" plus x-oold-range, with no scoped @context - rather than an embed. This is the linked-data analog of using a pointer instead of inlining a recursive data structure. A self-reference through the top-level @context (a property that nests the same type but carries no scoped context, so the global context maps the nested keys - e.g. a Process with sub-Processes) is not part of this graph and round-trips normally, bounded by the instance's actual depth.
See this rule in the specification (section: round-trip).
OOLD-RT-d9bd¶
- Level: MUST NOT
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A term must not coerce a literal to a datatype JSON-LD produces by default from a native JSON value (xsd:string, xsd:boolean, xsd:integer, xsd:double).
A term MUST NOT declare @type with a datatype that JSON-LD produces by default from a native JSON value: xsd:string (from a string), xsd:boolean (from a boolean), xsd:integer (from an integer number), and xsd:double (from a fractional number).
In context
A term MUST NOT declare @type with a datatype that JSON-LD produces by default from a native JSON value: xsd:string (from a string), xsd:boolean (from a boolean), xsd:integer (from an integer number), and xsd:double (from a fractional number). These are exactly the datatypes reconstruction converts back to native JSON values without an @type (JSONLD11-API, RDF to Object Conversion; see round-trip): the value arrives from RDF with no datatype, and a term is never selected against a conflicting or absent type mapping (JSONLD11-API, Term Selection), so the value reappears under the full predicate IRI instead. Coercing to one of these is redundant and lossy - a native JSON number already round-trips as xsd:integer or xsd:double with no coercion at all, and a boolean/string likewise. This is inherent to the compaction algorithm, not a tooling limitation; such terms are left plain (no @type), and the projection to RDF still yields the correct datatype from the native JSON type (JSONLD11-API, Data Round Tripping). The behaviour assumes reconstruction with native types (useNativeTypes), the mainstream default: a processor that instead keeps every literal as a typed value object would select the coerced term, but then plain native numbers and booleans no longer return as native JSON either (they come back as { "@value": ..., "@type": ... } objects), which defeats the structural model - so native-type reconstruction is assumed throughout.
See this rule in the specification (section: value-forms).
VER - Identification and versioning¶
OOLD-VER-2e63¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: no
- Since: 1.0.0-rc.1
A schema should be resolvable via its $id.
The schema SHOULD be resolvable via this URI.
In context
OO-LD schemas MUST have a $id (JSONSCHEMA §8.2.1) which works as a global and unique identifier of the schema. The value of $id MAY be an absolute URI (details below). The schema SHOULD be resolvable via this URI. The schema SHOULD have an annotation x-oold-uuid with a UUID value.
See this rule in the specification (section: identification).
OOLD-VER-3662¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A schema version should be stated with x-oold-version.
The schema version SHOULD be indicated by x-oold-version; a prior version MAY be indicated with x-oold-prior-version:
See this rule in the specification (section: versioning).
OOLD-VER-3b96¶
- Level: MUST
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A schema must have a $id serving as its global unique identifier.
OO-LD schemas MUST have a $id (JSONSCHEMA §8.2.1) which works as a global and unique identifier of the schema.
In context
OO-LD schemas MUST have a $id (JSONSCHEMA §8.2.1) which works as a global and unique identifier of the schema. The value of $id MAY be an absolute URI (details below). The schema SHOULD be resolvable via this URI. The schema SHOULD have an annotation x-oold-uuid with a UUID value.
See this rule in the specification (section: identification).
OOLD-VER-4261¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: no
- Since: 1.0.0-rc.1
Under schema-package versioning, the package version should be prepended before the schema id.
For schema-package versioning (recommended), the version of the package SHOULD be prepended before the schema's ID, e.g. https://example.org/my-package/2.0.0/b5203131-7321-46bb-8a11-acb3d1015840.schema.json.
In context
- For schema-package versioning (recommended), the version of the package SHOULD be prepended before the schema's ID, e.g.
https://example.org/my-package/2.0.0/b5203131-7321-46bb-8a11-acb3d1015840.schema.json. Since a package combines multiple schemas, the package version does in general not match the individual schema version.
See this rule in the specification (section: versioning).
OOLD-VER-534a¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
The schema version should be part of the schema location URL.
The version SHOULD be part of the schema's location:
In context
The version SHOULD be part of the schema's location:
- For single-schema versioning, the version SHOULD be appended after the schema name, e.g.
https://example.org/b5203131-7321-46bb-8a11-acb3d1015840.schema.json/1.1.0. - For schema-package versioning (recommended), the version of the package SHOULD be prepended before the schema's ID, e.g.
https://example.org/my-package/2.0.0/b5203131-7321-46bb-8a11-acb3d1015840.schema.json. Since a package combines multiple schemas, the package version does in general not match the individual schema version. - or a release tag on a code-hosting service, e.g.
https://raw.githubusercontent.com/MyOrg/my-package/refs/tags/2.0.0/b5203131-7321-46bb-8a11-acb3d1015840.schema.json. Such a location SHOULD name an immutable ref: a branch name identifies a moving target, whose content changes with every push, rather than a fixed version.
See this rule in the specification (section: versioning).
OOLD-VER-befc¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: no
- Since: 1.0.0-rc.1
Under single-schema versioning, the version should be appended after the schema name in the $id.
For single-schema versioning, the version SHOULD be appended after the schema name, e.g. https://example.org/b5203131-7321-46bb-8a11-acb3d1015840.schema.json/1.1.0.
In context
- For single-schema versioning, the version SHOULD be appended after the schema name, e.g.
https://example.org/b5203131-7321-46bb-8a11-acb3d1015840.schema.json/1.1.0.
See this rule in the specification (section: versioning).
OOLD-VER-c92e¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: no
- Since: 1.0.0-rc.1
A schema published for long-term reuse should be identified by a persistent identifier that resolves to its current hosting.
A raw hosting URL is convenient, but it binds the identifier to one host and one repository layout and carries no persistence guarantee, so a schema published for long-term reuse SHOULD be identified by a persistent identifier - a w3id.org or PURL redirect, or a DOI for a released package - that resolves to wherever the schema is currently hosted.
In context
A raw hosting URL is convenient, but it binds the identifier to one host and one repository layout and carries no persistence guarantee, so a schema published for long-term reuse SHOULD be identified by a persistent identifier - a w3id.org or PURL redirect, or a DOI for a released package - that resolves to wherever the schema is currently hosted. The persistent identifier is then the $id, and the raw URL is only where it happens to resolve today, so the schema survives a move between hosts without changing identity.
See this rule in the specification (section: versioning).
OOLD-VER-d826¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: no
- Since: 1.0.0-rc.1
A version carried in a schema location should be pinned to an immutable ref, not a mutable branch.
Such a location SHOULD name an immutable ref: a branch name identifies a moving target, whose content changes with every push, rather than a fixed version.
In context
- or a release tag on a code-hosting service, e.g.
https://raw.githubusercontent.com/MyOrg/my-package/refs/tags/2.0.0/b5203131-7321-46bb-8a11-acb3d1015840.schema.json. Such a location SHOULD name an immutable ref: a branch name identifies a moving target, whose content changes with every push, rather than a fixed version.
See this rule in the specification (section: versioning).
OOLD-VER-edb9¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A schema should carry an x-oold-uuid annotation holding a UUID value.
The schema SHOULD have an annotation x-oold-uuid with a UUID value.
In context
OO-LD schemas MUST have a $id (JSONSCHEMA §8.2.1) which works as a global and unique identifier of the schema. The value of $id MAY be an absolute URI (details below). The schema SHOULD be resolvable via this URI. The schema SHOULD have an annotation x-oold-uuid with a UUID value.
See this rule in the specification (section: identification).
EXT - Standard extensions (JSON-LD and JSON Schema)¶
OOLD-EXT-1dc8¶
- Level: MUST NOT
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A predicate_id must not be a bare local name.
A bare local name (exactMatch) MUST NOT be used as a predicate_id.
In context
predicate_id is a SKOS mapping predicate - skos:exactMatch (the default when the slot is absent), skos:closeMatch, skos:broadMatch, skos:narrowMatch or skos:relatedMatch - relating the term's primary IRI (subject) to the synonym IRI (object); it decides which entries denote equivalence. It MUST be written as a full IRI or a CURIE and compared by expansion to an absolute IRI, the same rule the synonym keys follow, so skos:exactMatch and http://www.w3.org/2004/02/skos/core#exactMatch are one predicate. x-oold-context is a schema-level keyword consumed by OO-LD processors (it is promoted into a clean @context before any generic JSON-LD processor runs), so its CURIEs - the synonym keys and the predicate_id / mapping_set_id values alike - are expanded not against the instance @context but against a fixed well-known prefix set the meta-schema defines (skos, rdfs, owl, xsd, sssom), reached through the schema's $schema. The contract therefore holds without the author redeclaring those prefixes in the data context. A bare local name (exactMatch) MUST NOT be used as a predicate_id.
See this rule in the specification (section: synonyms).
OOLD-EXT-1f92¶
- Level: RECOMMENDED
- Applies to: document
- Machine-checkable: no
- Since: 1.0.0-rc.1
iri-reference is the recommended default format for an IRI-valued property.
By RFC3987 this accepts absolute IRIs, compact IRIs (ex:alice, schema:Person) and context-relative references alike - the forms OO-LD instances routinely use - so it is the RECOMMENDED default.
In context
- Any IRI reference -
"format": "iri-reference". By RFC3987 this accepts absolute IRIs, compact IRIs (ex:alice,schema:Person) and context-relative references alike - the forms OO-LD instances routinely use - so it is the RECOMMENDED default. It also accepts a bare term such asalice, expanded against the context's@base/@vocab.
See this rule in the specification (section: range-reference-form).
OOLD-EXT-2542¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
Value terms should not collide with JSON-LD keyword aliases or other context terms.
The value terms SHOULD also be kept from colliding with JSON-LD keyword aliases (id, type) or other context terms, since a value term shares the context's global term namespace - a term added for a value would otherwise also rewrite a property or keyword of the same name.
In context
Because @vocab expands an unmatched string against the vocabulary - concatenating it onto the default vocabulary base when one is set (minting a new IRI), or leaving it a relative IRI when none is - a typo silently becomes a stray IRI rather than an error. A property coerced "@type": "@vocab" therefore SHOULD constrain its values with an enum of the value terms (optionally named with x-enum-varnames) or with x-oold-range, so only intended individuals are accepted. The value terms SHOULD also be kept from colliding with JSON-LD keyword aliases (id, type) or other context terms, since a value term shares the context's global term namespace - a term added for a value would otherwise also rewrite a property or keyword of the same name. Confining the value terms to the property's own scoped @context keeps them out of that shared namespace, since they then resolve only for that property's values; naming them with opaque identifiers such as UUIDs avoids the clash where readability is not required.
See this rule in the specification (section: value-term-aliases).
OOLD-EXT-2b61¶
- Level: MUST
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A compact-IRI prefix used by a property must be defined in the @context.
Compact form specifically - a "pattern" such as "^[A-Za-z_][\\w.-]:(?!//)\\S$", which accepts ex:alice and schema:Person while rejecting http://…; the prefix MUST be defined in the @context.
In context
- Stricter, ASCII only -
"format": "uri"or"uri-reference", where values are known not to use internationalized (non-ASCII) IRIs. - Compact form specifically - a
"pattern"such as"^[A-Za-z_][\\w.-]:(?!//)\\S$", which acceptsex:aliceandschema:Personwhile rejectinghttp://…; the prefix MUST be defined in the@context.
See this rule in the specification (section: range-reference-form).
OOLD-EXT-391e¶
- Level: MUST
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
A loader that dereferences a target validates it against the declared range and does not assume the target conforms.
A loader that dereferences a target MUST validate it against that range before treating it as a member, and MUST NOT assume the target conforms, since the target is a separate document that may change independently of the reference.
In context
An x-oold-range value is a reference: the property holds the target's IRI, and an OO-LD-aware loader MAY dereference that IRI to obtain the target document itself, so a large or shared object can live in a separate document and be pulled in on demand (data bundling). A published reference SHOULD point at a target that validates against the property's declared range. A loader that dereferences a target MUST validate it against that range before treating it as a member, and MUST NOT assume the target conforms, since the target is a separate document that may change independently of the reference. This holds whether the reference is written as a bare IRI string or as a { "@id": … } object; generic tooling leaves it unresolved, exactly as it leaves x-oold-ref (see why-x-oold-ref).
See this rule in the specification (section: range-of-properties).
OOLD-EXT-3fe9¶
- Level: MUST
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
References inside x-oold-range must use x-oold-ref, never $ref.
References to other schemas inside x-oold-range MUST use x-oold-ref, never $ref (see below).
In context
- An OO-LD subschema, the most expressive form. Unions (
anyOf/oneOf), intersections (allOf) and inline constraints can be combined to describe an anonymous subclass. References to other schemas insidex-oold-rangeMUST usex-oold-ref, never$ref(see below). The single-IRI form (1) is a shorthand for{ "allOf": [ { "x-oold-ref": "Organization.schema.json" } ] }:
See this rule in the specification (section: range-of-properties).
OOLD-EXT-436a¶
- Level: SHOULD
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
For OpenAPI 3.0, deliver the context and type per class as vendor extensions.
For OpenAPI 3.0, which rejects unprefixed keywords in a Schema Object (and typically bundles several classes with no document root to host one @context), the context and type SHOULD be delivered per class as x-jsonld-context and x-jsonld-type following REST API Linked Data Keywords: @context maps to x-jsonld-context and x-oold-instance-rdf-type to x-jsonld-type.
In context
- For OpenAPI 3.0, which rejects unprefixed keywords in a Schema Object (and typically bundles several classes with no document root to host one
@context), the context and type SHOULD be delivered per class asx-jsonld-contextandx-jsonld-typefollowing REST API Linked Data Keywords:@contextmaps tox-jsonld-contextandx-oold-instance-rdf-typetox-jsonld-type. That draft requires references inside these keywords not to be dereferenced automatically, consistent with thex-oold-refrule (see why-x-oold-ref). The mapping is reversible, so such an export can be read back into an OO-LD schema.
See this rule in the specification (section: semantic-delivery).
OOLD-EXT-4966¶
- Level: MUST
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
Promotion selects one synonym per term for the target profile, writes it as the term definition and drops the x-oold-sssom blocks.
To promote x-oold-context into a real @context, a preprocessor MUST select one synonym per term for a target profile, write { "@id": <synonym IRI>, ...fragment without x-oold-sssom } as that term's definition, and drop the x-oold-sssom blocks, so standard JSON-LD tools then run on a clean context.
In context
Selection. To promote x-oold-context into a real @context, a preprocessor MUST select one synonym per term for a target profile, write { "@id": <synonym IRI>, ...fragment without x-oold-sssom } as that term's definition, and drop the x-oold-sssom blocks, so standard JSON-LD tools then run on a clean context. A profile is expressed either as an ordered list of IRI namespaces (ontology-family priority - schema: before bfo: before emmo:) or as one or more mapping_set_ids (a set may span namespaces, e.g. a PMDco profile of pmd: plus reused obo: terms). A term with no synonym matching the target keeps its default @context IRI. Selection MUST NOT use a synonym from outside the target profile; where the profile is an ordered list, the highest-priority match wins and a lower-priority entry is selected only where no higher one matches.
See this rule in the specification (section: synonyms).
OOLD-EXT-5184¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A schema should declare the OO-LD dialect meta-schema as its $schema.
An OO-LD schema SHOULD declare the OO-LD dialect meta-schema (which extends 2020-12) as its $schema, e.g. "$schema": "https://oo-ld.org/latest/meta/oold-meta-schema.json" - pinning a specific version (e.g. .../0.4.0/meta/oold-meta-schema.json) for reproducibility.
In context
OO-LD targets JSONSCHEMA (2020-12) as its normative dialect. An OO-LD schema SHOULD declare the OO-LD dialect meta-schema (which extends 2020-12) as its $schema, e.g. "$schema": "https://oo-ld.org/latest/meta/oold-meta-schema.json" - pinning a specific version (e.g. .../0.4.0/meta/oold-meta-schema.json) for reproducibility. Declaring the plain 2020-12 meta-schema (https://json-schema.org/draft/2020-12/schema) remains valid for tools that only understand standard JSON Schema.
See this rule in the specification (section: jsonschema-extensions).
OOLD-EXT-557e¶
- Level: MUST
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
A predicate_id is written as a full IRI or CURIE and compared by expansion to an absolute IRI.
It MUST be written as a full IRI or a CURIE and compared by expansion to an absolute IRI, the same rule the synonym keys follow, so skos:exactMatch and http://www.w3.org/2004/02/skos/core#exactMatch are one predicate.
In context
predicate_id is a SKOS mapping predicate - skos:exactMatch (the default when the slot is absent), skos:closeMatch, skos:broadMatch, skos:narrowMatch or skos:relatedMatch - relating the term's primary IRI (subject) to the synonym IRI (object); it decides which entries denote equivalence. It MUST be written as a full IRI or a CURIE and compared by expansion to an absolute IRI, the same rule the synonym keys follow, so skos:exactMatch and http://www.w3.org/2004/02/skos/core#exactMatch are one predicate. x-oold-context is a schema-level keyword consumed by OO-LD processors (it is promoted into a clean @context before any generic JSON-LD processor runs), so its CURIEs - the synonym keys and the predicate_id / mapping_set_id values alike - are expanded not against the instance @context but against a fixed well-known prefix set the meta-schema defines (skos, rdfs, owl, xsd, sssom), reached through the schema's $schema. The contract therefore holds without the author redeclaring those prefixes in the data context. A bare local name (exactMatch) MUST NOT be used as a predicate_id.
See this rule in the specification (section: synonyms).
OOLD-EXT-6007¶
- Level: SHOULD
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
An OO-LD-aware tool resolves x-oold-ref lazily and handles a cyclic reference graph by terminating rather than recursing indefinitely.
An OO-LD-aware tool SHOULD resolve x-oold-ref lazily, and MUST handle a cyclic reference graph - terminating and returning the references it has already resolved, rather than recursing indefinitely - since the graph it opts into may be unbounded or self-referential.
In context
x-oold-ref avoids this. Generic tools only follow the standard $ref keyword, so they leave x-oold-ref untouched. An OO-LD-aware tool SHOULD resolve x-oold-ref lazily, and MUST handle a cyclic reference graph - terminating and returning the references it has already resolved, rather than recursing indefinitely - since the graph it opts into may be unbounded or self-referential. The standard $ref continues to be used for ordinary schema composition (allOf, properties, $defs), which bundlers are expected to resolve. Because the only difference is the keyword name, the mapping is reversible: an OO-LD-aware tool can mechanically replace x-oold-ref with $ref to obtain a plain, fully-resolvable JSON Schema - the explicit opt-in to resolving the (possibly cyclic) graph.
See this rule in the specification (section: why-x-oold-ref).
OOLD-EXT-61aa¶
- Level: SHOULD
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
A consumer accepting arbitrary JSON Schema keywords should receive the native form unchanged.
A consumer that accepts arbitrary JSON Schema keywords SHOULD receive the native form unchanged.
In context
- A consumer that accepts arbitrary JSON Schema keywords SHOULD receive the native form unchanged. This covers plain JSON Schema 2020-12 validators, OpenAPI 3.1, and - because they place no restriction on
@context- Model Context Protocol tool schemas (inputSchema/outputSchema) as well as LLM tool-use and structured-output APIs, which carry the context through and can use it as grounding.
See this rule in the specification (section: semantic-delivery).
OOLD-EXT-6312¶
- Level: MUST NOT
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
The multilang keywords must not be used to localize an instance value; the standard JSON-LD mechanism is used instead.
To localize a value of an instance - a translatable string in the data that should round-trip to language-tagged RDF literals - the keywords above MUST NOT be used; the standard JSON-LD mechanism MUST be used instead.
In context
To localize a value of an instance - a translatable string in the data that should round-trip to language-tagged RDF literals - the keywords above MUST NOT be used; the standard JSON-LD mechanism MUST be used instead. There are two equivalent JSON-LD-native ways to carry such a value, both producing the same language-tagged literals.
See this rule in the specification (section: localizing-instance-values).
OOLD-EXT-6ea3¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
An IRI-valued property should constrain its lexical form with an IRI/URI-family format.
Its lexical form SHOULD be constrained with an IRI/URI-family format so that malformed values are rejected; the choices, from most to least permissive:
In context
The value of an IRI-valued property is a JSON string. Its role as a reference comes from the @context ("@type": "@id") and its class from x-oold-range. Its lexical form SHOULD be constrained with an IRI/URI-family format so that malformed values are rejected; the choices, from most to least permissive:
- Any IRI reference -
"format": "iri-reference". By RFC3987 this accepts absolute IRIs, compact IRIs (ex:alice,schema:Person) and context-relative references alike - the forms OO-LD instances routinely use - so it is the RECOMMENDED default. It also accepts a bare term such asalice, expanded against the context's@base/@vocab. - Absolute IRIs only -
"format": "iri". A compact IRI is itself a valid absolute IRI (schemeex, pathalice), soiriacceptsex:alice; choose it to additionally forbid relative references. - Stricter, ASCII only -
"format": "uri"or"uri-reference", where values are known not to use internationalized (non-ASCII) IRIs.
See this rule in the specification (section: range-reference-form).
OOLD-EXT-7256¶
- Level: SHOULD NOT
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
Entries that are not exactMatch should not be co-emitted unless a consumer explicitly requests it.
By default a converter co-emits only skos:exactMatch entries; entries whose predicate_id is skos:closeMatch/broadMatch/narrowMatch/relatedMatch SHOULD NOT be co-emitted unless a consumer explicitly requests it, since such a triple asserts a broader, narrower or merely related relation, not that the value holds under the synonym property, so the requester takes responsibility for that reading.
In context
Co-emission. Selection yields one IRI per term; for interoperability a converter MAY additionally co-emit the instance value under other synonyms' IRIs. This is a pragmatic interoperability aid, not a logical entailment: skos:exactMatch records that two terms are interchangeable across a wide range of applications, but it is not owl:equivalentProperty / owl:equivalentClass and licenses no reasoner inference - which is exactly why the mapping predicates are SKOS (reasoner-safe) rather than OWL. By default a converter co-emits only skos:exactMatch entries; entries whose predicate_id is skos:closeMatch/broadMatch/narrowMatch/relatedMatch SHOULD NOT be co-emitted unless a consumer explicitly requests it, since such a triple asserts a broader, narrower or merely related relation, not that the value holds under the synonym property, so the requester takes responsibility for that reading.
See this rule in the specification (section: synonyms).
OOLD-EXT-7c5d¶
- Level: MUST
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
A conforming mapping processor reads exactly the synonym IRI, the term-definition fragment, predicate_id and mapping_set_id from an entry.
A conforming OO-LD mapping processor MUST read exactly four things from each entry: the synonym IRI (the key), the promotable term-definition fragment, and two x-oold-sssom slots - predicate_id and mapping_set_id.
In context
Processing contract. A conforming OO-LD mapping processor MUST read exactly four things from each entry: the synonym IRI (the key), the promotable term-definition fragment, and two x-oold-sssom slots - predicate_id and mapping_set_id. Conformance MUST NOT depend on anything else an entry carries (the rest of x-oold-sssom, any further fragment keys); a processor MAY interpret such keys as its own extension, and MUST carry them through unchanged where it rewrites an entry rather than promoting it - promotion deliberately drops the x-oold-sssom blocks, as Selection describes below. Those two slots, over the SKOS predicate vocabulary, are the whole stable contract an implementation depends on.
See this rule in the specification (section: synonyms).
OOLD-EXT-8f62¶
- Level: MUST NOT
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
Selection must not use a synonym outside the target profile; within an ordered profile the highest-priority match wins.
Selection MUST NOT use a synonym from outside the target profile; where the profile is an ordered list, the highest-priority match wins and a lower-priority entry is selected only where no higher one matches.
In context
Selection. To promote x-oold-context into a real @context, a preprocessor MUST select one synonym per term for a target profile, write { "@id": <synonym IRI>, ...fragment without x-oold-sssom } as that term's definition, and drop the x-oold-sssom blocks, so standard JSON-LD tools then run on a clean context. A profile is expressed either as an ordered list of IRI namespaces (ontology-family priority - schema: before bfo: before emmo:) or as one or more mapping_set_ids (a set may span namespaces, e.g. a PMDco profile of pmd: plus reused obo: terms). A term with no synonym matching the target keeps its default @context IRI. Selection MUST NOT use a synonym from outside the target profile; where the profile is an ordered list, the highest-priority match wins and a lower-priority entry is selected only where no higher one matches.
See this rule in the specification (section: synonyms).
OOLD-EXT-adcc¶
- Level: MUST NOT
- Applies to: implementation
- Machine-checkable: no
- Since: 1.0.0-rc.1
Conformance must not depend on anything an entry carries beyond the four contract members.
Conformance MUST NOT depend on anything else an entry carries (the rest of x-oold-sssom, any further fragment keys); a processor MAY interpret such keys as its own extension, and MUST carry them through unchanged where it rewrites an entry rather than promoting it - promotion deliberately drops the x-oold-sssom blocks, as Selection describes below.
In context
Processing contract. A conforming OO-LD mapping processor MUST read exactly four things from each entry: the synonym IRI (the key), the promotable term-definition fragment, and two x-oold-sssom slots - predicate_id and mapping_set_id. Conformance MUST NOT depend on anything else an entry carries (the rest of x-oold-sssom, any further fragment keys); a processor MAY interpret such keys as its own extension, and MUST carry them through unchanged where it rewrites an entry rather than promoting it - promotion deliberately drops the x-oold-sssom blocks, as Selection describes below. Those two slots, over the SKOS predicate vocabulary, are the whole stable contract an implementation depends on.
See this rule in the specification (section: synonyms).
OOLD-EXT-af50¶
- Level: REQUIRED
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
JSON Schema 2020-12 is required as the dialect, because composition places $ref alongside sibling keywords.
2020-12 is REQUIRED, not merely preferred: OO-LD's composition places $ref alongside sibling keywords (e.g. a property carrying type, x-oold-range and @context, or allOf: [{$ref: ...}] next to properties).
In context
2020-12 is REQUIRED, not merely preferred: OO-LD's composition places $ref alongside sibling keywords (e.g. a property carrying type, x-oold-range and @context, or allOf: [{$ref: ...}] next to properties). Keywords adjacent to $ref are only evaluated from JSON Schema 2019-09 onward; in Draft 4 and Draft 7 they are ignored (JSONSCHEMA §8.2.3.1). Keywords such as const (used throughout this document) are likewise only available from draft-06 onward. Migration from the earlier Draft-4-style notation: rename definitions to $defs, id to $id, and use the numeric form of exclusiveMinimum/exclusiveMaximum instead of the boolean form.
See this rule in the specification (section: jsonschema-extensions).
OOLD-EXT-dd76¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A schema using multilingual annotations should still provide a default title and description.
A schema SHOULD still provide a default title / description; a consumer that has no entry for the requested language falls back to that default.
In context
The JSON Schema annotation keywords title and description carry a single, default human-readable string used by tooling (for example for UI generation). To provide localized variants, OO-LD adds the keywords x-oold-multilang-title and x-oold-multilang-description. Their value MUST be an object whose keys are BCP 47 language tags (e.g. en, de, en-GB) and whose values are the translated strings. A schema SHOULD still provide a default title / description; a consumer that has no entry for the requested language falls back to that default. These keywords localize the schema's own labels and are not interpreted as JSON-LD.
See this rule in the specification (section: localizing-schema-annotations).
OOLD-EXT-ddda¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A generated context should declare @version 1.1 as a JSON number.
Generated OO-LD contexts SHOULD therefore declare "@version": 1.1 (the JSON number 1.1, not the string "1.1").
In context
Generated OO-LD contexts SHOULD therefore declare "@version": 1.1 (the JSON number 1.1, not the string "1.1"). Modern processors default to the 1.1 processing mode, so this is a guard rather than a strict requirement: it prevents a JSON-LD 1.0 processor from silently mis-processing a 1.1 document (JSON-LD11 §4.1.1). Because the first encountered @version entry determines the processing mode, it is sufficient to declare "@version": 1.1 once in the base context of a composition (for example a root Thing schema).
See this rule in the specification (section: processing-mode).
OOLD-EXT-ece0¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: no
- Since: 1.0.0-rc.1
A published reference should point at a target that validates against the property's declared range.
A published reference SHOULD point at a target that validates against the property's declared range.
In context
An x-oold-range value is a reference: the property holds the target's IRI, and an OO-LD-aware loader MAY dereference that IRI to obtain the target document itself, so a large or shared object can live in a separate document and be pulled in on demand (data bundling). A published reference SHOULD point at a target that validates against the property's declared range. A loader that dereferences a target MUST validate it against that range before treating it as a member, and MUST NOT assume the target conforms, since the target is a separate document that may change independently of the reference. This holds whether the reference is written as a bare IRI string or as a { "@id": … } object; generic tooling leaves it unresolved, exactly as it leaves x-oold-ref (see why-x-oold-ref).
See this rule in the specification (section: range-of-properties).
OOLD-EXT-ef09¶
- Level: MUST
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
x-oold-multilang-title/description must map BCP 47 language tags to translated strings.
Their value MUST be an object whose keys are BCP 47 language tags (e.g. en, de, en-GB) and whose values are the translated strings.
In context
The JSON Schema annotation keywords title and description carry a single, default human-readable string used by tooling (for example for UI generation). To provide localized variants, OO-LD adds the keywords x-oold-multilang-title and x-oold-multilang-description. Their value MUST be an object whose keys are BCP 47 language tags (e.g. en, de, en-GB) and whose values are the translated strings. A schema SHOULD still provide a default title / description; a consumer that has no entry for the requested language falls back to that default. These keywords localize the schema's own labels and are not interpreted as JSON-LD.
See this rule in the specification (section: localizing-schema-annotations).
OOLD-EXT-fdd8¶
- Level: SHOULD
- Applies to: document
- Machine-checkable: yes
- Since: 1.0.0-rc.1
A property coerced @type @vocab should constrain its values with an enum or x-oold-range.
A property coerced "@type": "@vocab" therefore SHOULD constrain its values with an enum of the value terms (optionally named with x-enum-varnames) or with x-oold-range, so only intended individuals are accepted.
In context
Because @vocab expands an unmatched string against the vocabulary - concatenating it onto the default vocabulary base when one is set (minting a new IRI), or leaving it a relative IRI when none is - a typo silently becomes a stray IRI rather than an error. A property coerced "@type": "@vocab" therefore SHOULD constrain its values with an enum of the value terms (optionally named with x-enum-varnames) or with x-oold-range, so only intended individuals are accepted. The value terms SHOULD also be kept from colliding with JSON-LD keyword aliases (id, type) or other context terms, since a value term shares the context's global term namespace - a term added for a value would otherwise also rewrite a property or keyword of the same name. Confining the value terms to the property's own scoped @context keeps them out of that shared namespace, since they then resolve only for that property's values; naming them with opaque identifiers such as UUIDs avoids the clash where readability is not required.
See this rule in the specification (section: value-term-aliases).