Copyright © the OO-LD contributors. This document is made available under the CC0 1.0 Universal Public Domain Dedication; W3C liability, trademark and document-license rules do not apply.
Object-Oriented Linked Data (OO-LD) connects the structural modelling of objects and subobjects with the modelling of their semantic relations, by combining two existing standards - [[JSONSCHEMA]] and a [[JSON-LD11]] context - in a single document. A single OO-LD document is at once a valid JSON Schema and a reference-able JSON-LD remote context, so that one source can drive validation, RDF generation, code generation, user interfaces and API definitions using the existing JSON Schema and JSON-LD tooling.
This is a community specification produced by the OO-LD project. It is a work in progress and may change at any time. It is not a W3C Standard nor is it on the W3C Standards Track. Feedback and issues are welcome in the issue tracker.
A companion, example-driven guide (primer) introduces the same concepts in a didactic, step-by-step form. This document is the normative specification.
OO-LD Schema aims to connect the structural modelling of objects and subobjects with the modelling of the semantic relations without reinventing the wheel. It therefore combines existing standards, primarily JSON Schema and a JSON-LD context in the same document.
What distinguishes OO-LD from other approaches that unify structure and semantics is that the artefact is the source. A single OO-LD document is at the same time a valid JSON Schema and a referenceable JSON-LD remote context, so there is no separate modelling language to learn and no build step that generates - and then has to keep in sync - a separate schema and a separate context. The same property extends to the instance level: an OO-LD instance is a valid JSON-LD document, and OO-LD-aware tooling (for example the oold library) resolves the IRIs it references into linked objects, so a stored graph can be navigated as objects rather than as loose identifiers.
An OO-LD document is always a valid JSON document. This ensures that all the standard JSON libraries work seamlessly with OO-LD documents.
An OO-LD instance document is always a valid JSON-LD document. This ensures that all the standard JSON-LD libraries work seamlessly with OO-LD instance documents.
An OO-LD schema document is always both a valid JSON Schema document and JSON-LD remote context. This ensures that all the standard JSON Schema and JSON-LD libraries work seamlessly with OO-LD schema documents.
An OO-LD schema document allows the developer to express the syntax of a JSON instance document side by side with its semantics in a single source.
In addition, syntactical and semantic definitions can also be applied to external JSON instance documents that reference OO-LD schema documents.
This allows to specify well-defined patterns in a directed graph and enables tools relying on a hierarchical object structure to produce data for and consume data from such a graph.
OO-LD schema documents allow to specify all information that is needed to automatically transform data between semantically equivalent but syntactically different notations.
Data modelling is commonly described in three layers: a conceptual layer (RDFS, OWL), a logical layer (SHACL, ShEx) and a physical layer (JSON Schema, XML Schema). Keeping these layers consistent when they are authored separately is a recurring problem. OO-LD is a physical-layer artefact that carries enough conceptual annotation - its JSON-LD @context together with keywords such as x-oold-range (see ) - to generate the logical layer (SHACL shapes) and the conceptual layer (OWL) from the same source, so the layers cannot drift apart.
OO-LD does not aim to replace established modelling frameworks. Frameworks such as LinkML, SPDX 3.0 and TreeLDR compile a bespoke source into JSON Schema and a separate JSON-LD context; OO-LD instead annotates JSON Schema in place and offers generated bridges to the forms other ecosystems expect. A consumer that cannot accept a top-level @context - OpenAPI 3.0, or a strict LLM structured-output subset - is served a generated form (x-jsonld-context / x-jsonld-type, or annotations folded into title / description; see ) rather than a hand-maintained parallel document, so the single OO-LD source stays authoritative. This positions OO-LD as an interlingua in the physical layer, not as another isolated syntax.
A JSON Schema keyword names a property with a local string; an RDF predicate is a global IRI. RDF-based schema languages such as SHACL therefore require every participating term to be a committed, globally named IRI before data can be expressed or validated as a graph: RDF has no notion of a field whose meaning is not yet decided. This is not a question of how many vocabularies are involved - SHACL validates across many vocabularies at once - but of when the commitment must be made. In domains where a shared vocabulary is missing, contested, or still emerging, that eager, per-term commitment is a barrier to starting.
OO-LD inverts the order. Because it is JSON Schema first, a term exists as a plain structural property with no semantics attached; an author MAY leave it unmapped, map it to a single IRI, or map it to several concurrent IRIs (see and ). An unmapped term produces no triples under JSON-LD expansion; to prevent such terms from being dropped silently, an author MAY declare @vocab in the @context, which maps every otherwise-unmapped term to a default (local) namespace so it still round-trips to RDF under a provisional IRI until a curated mapping is assigned. Any data can be serialized as JSON and therefore described by a schema, so the structural model - validation, forms, code generation, transport - is always available, and semantics can be added later, incrementally, one term at a time. The floor on this deferral is identity, not zero: graph-shaped data still needs identifiers for its links (carried by IRI-valued properties and ), but the vocabulary and meaning of each field can be deferred without blocking any of the structural uses. This is the boundary to RDF/SHACL: they cannot withhold semantic commitment, OO-LD can.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in [[!RFC2119]].
The following terms are used throughout this specification:
The core idea is that an [=OO-LD schema=] is always both a valid JSON Schema and a reference-able JSON-LD [=remote context=] as defined in [[JSON-LD11]] §3.1 (not a JSON-LD document). In this way a complete OO-LD class / schema hierarchy is consume-able by JSON Schema-only and JSON-LD-only tools while OO-LD-aware tools can provide extended features on top (e.g. UI autocomplete dropdowns for string-IRI fields based on a SPARQL backend, or SHACL shape / JSON-LD frame generation).
There is an asymmetry between how schemas and instances are consumed:
@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 @context to the schema itself and produce incorrect triples.This asymmetry is what lets a single document serve both as a JSON Schema $ref target and as a JSON-LD remote @context for the same resource. Concretely: an instance is processed directly as a JSON-LD document (e.g. jsonld.toRDF(instance)), which loads the schema as a remote context via the instance's @context; a schema is only ever referenced as that context and MUST NOT itself be expanded as a document.
A class B extends a class A by referencing it in both allOf (so JSON Schema validators apply A's rules when validating B instances) and @context (so JSON-LD processors resolve A's term mappings). B instances are therefore valid A instances and carry all of A's properties alongside B's own additions. Building types from multiple independent schemas is covered in .
Composition is how an [=OO-LD schema=] incorporates multiple independent schemas, each contributing its own properties and JSON-LD term mappings, without requiring a shared parent class. This lets you build complex types by assembling reusable building blocks - for example, attaching a geolocation schema and a contact schema to a single resource type. The rules below govern how the resulting @context is assembled automatically, so that no post-processing step is needed.
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. $ref within properties of type: object MUST be listed as a scoped JSON-LD context. $ref within all other property types and at the root level of the OO-LD schema MUST be listed at the root level of the JSON-LD context. In case of multiple $ref within allOf the corresponding remote contexts are merged into an array-valued @context (see ). 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.
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 ([[JSON-LD11]] §4.1.5). 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.
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.
Where branches genuinely need different mappings for the same keyword, do not place them at the root; scope them so each mapping applies only where its branch applies, using JSON-LD scoped contexts:
Type-scoped contexts when the branches are distinguished by @type. The
scoped @context is attached to the term used as the type value and is activated only for nodes carrying that @type:
{
"@context": {
"Sensor": { "@id": "ex:Sensor", "@context": { "reading": "ex:temperature" } },
"Gauge": { "@id": "ex:Gauge", "@context": { "reading": "ex:pressure" } }
}
}
Here { "@type": "Sensor", "reading": 21 } maps reading to ex:temperature, while { "@type": "Gauge", "reading": 3 } maps the same keyword to ex:pressure.
@context) and applies only within that property's value, so the same keyword can resolve differently under different parents.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. Contexts combined in a single array MUST share the same @propagate value.
Protected terms (@protected). A schema MAY mark terms @protected to prevent later contexts from silently redefining them. When contexts are combined via allOf, redefining a protected term to a different IRI is an error unless the new definition is identical; property-scoped contexts are exempt and may override protected terms within their subtree. Relying on @protected therefore constrains which schemas a schema can be combined with.
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).
JSON Schema's validation algebra is purely conjunctive: allOf requires an instance to satisfy every subschema, and the specification defines no merge of the subschemas' keyword values ([[JSONSCHEMA]] §10.2.1.1). Several consumers nonetheless require a single [=resolved schema=] view rather than a conjunction: a UI generator needs exactly one title per field, a code generator flattens an inheritance chain into one class, and an OO-LD preprocessor must produce one @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.
This single model governs every place OO-LD collapses composition into a resolved value: single-valued annotations such as title and x-oold-multilang-title resolve most-derived-wins, constraints resolve narrow-only, and additive maps merge by key. A preprocessor applying it produces exactly the view that UI and code generators already compute, so no separate "resolved schema" format is needed.
Because allOf composition is conjunctive, additionalProperties: false on one subschema rejects the members that the other composed subschemas contribute, so it cannot close a composed object. To close such an object - rejecting members that no composed subschema declares - use unevaluatedProperties: false ([[JSONSCHEMA]] §11.3), which is evaluated after the allOf branches and therefore accounts for their properties. A schema closed this way should still allow the instance-level $schema and @context members (see ).
An [=OO-LD instance=] is a JSON document that conforms to an [=OO-LD schema=]. It references that schema in two ways, both pointing at the same (preferably versioned) schema URL:
@context - the schema URL, loaded as a JSON-LD remote context. This is what makes the instance a JSON-LD document.$schema - the schema URL, identifying the schema the instance is intended to validate against.Instances SHOULD use a versioned schema URL so that it is unambiguous which schema version they conform to.
$schemaIn standard JSON Schema, $schema identifies the dialect (meta-schema), not the schema an instance validates against ([[JSONSCHEMA]] §8.1.1); JSON Schema does not define an in-band way for an instance to point at its own schema. OO-LD therefore uses $schema on instances as a convention: standard JSON Schema validators treat it as ordinary data, while editors (VS Code, JetBrains, JSON Schema Store) and CI checks (e.g. check-json-schema-meta) honor it. Where the instance is served over HTTP, the standards-conformant alternative is the describedby link relation ([[JSONSCHEMA]] §9.5.1.1), optionally with the profile media-type parameter ([[RFC6906]]):
An OO-LD-aware tool determines an instance's schema in the following order:
$schema value, if present;@context, if the referenced document declares itself to be an OO-LD schema;@type (see below) - but only when at least one of the type IRIs resolves to an OO-LD schema.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).
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.
@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.
@id)An instance that represents an identifiable entity is identified by an @id - the IRI of that entity. This is the JSON-LD node identifier, distinct from $schema / @context (which identify the schema) and from the schema's own $id / x-oold-uuid. Without an @id the entity is an anonymous blank node and cannot be referenced (for example as the target of an x-oold-range or @reverse relation).
To keep instance keys variable-name-friendly, schemas SHOULD expose @id through an aliased id property (as with type -> @type):
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-....
Embedded value objects that have no independent identity (for example an Address embedded in an Organization) MAY omit @id and remain blank nodes.
The type and semantics of an instance are owned by the OO-LD schema it references; an instance is therefore not required to carry an inline type, and a schema version may remap to different ontology terms without rewriting existing data.
A schema declares the rdf:type(s) of its instances with the x-oold-instance-rdf-type keyword (always a list of IRIs, e.g. ["schema:Person"]):
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.
Alternatively, an instance MAY carry the type inline as a type property (self-describing data). The schema maps the type term to the JSON-LD keyword @type with a simple alias and gives it a default; the value MAY be a single IRI or a list of IRIs, and this property named type is distinct from the JSON Schema type keyword. No @type: @id coercion is needed because JSON-LD already interprets @type values as IRIs:
const would also fix the type, but it would prevent a subclass from overriding or extending it (for example a subclass adding schema:Researcher). With default a subclass can redefine the property.
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.
Under composition, x-oold-instance-rdf-type follows the same most-derived-wins rule as the rest of the schema (see ): the nearest declaration in the allOf chain is authoritative and REPLACES - it does not append to - a base class's value. 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"]).
A property whose value denotes another resource takes one of three forms in an instance, distinguished by the shape of the JSON value, and each projects to RDF differently:
"Mainstreet 1";@id (or its id alias), e.g. { "id": "https://example.org/PlaceA" }, denoting an independent entity by IRI;{ "type": "PostalAddress", "streetAddress": "..." }, which becomes a blank node.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".
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 ); a model ecosystem SHOULD adopt one of them consistently:
@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.p with @type: "@id" (a bare IRI string reference, plus embedded objects via a scoped @context) and a companion p_text that is a plain term for the literal.xsd:string is RDF's default datatype and is elided from plain string literals, so a term declaring @type: "xsd:string" is never selected when a string value is compacted back from RDF - the value would reappear under the full predicate IRI instead. A literal term MUST be left plain (no @type). Non-default datatypes (xsd:date, xsd:integer, xsd:float, ...) stay explicit on the literal and do round-trip, so datatype coercion for those is correct.
Whichever pattern is chosen, x-oold-range records the permitted target type(s) on the reference and embedded branches (see ).
A reference can carry sibling members beside @id (a cached label, coordinates, ...) for denormalization or offline display. In RDF these become ordinary assertions about the referenced IRI, indistinguishable from authoritative statements - their status as a cache is not recoverable from the data, and a generic consumer reads them as authoritative. Treating them instead as indicative, potentially outdated copies whose authoritative values live on the referenced target (so the target's own property wins on conflict) is a contract an implementation or ecosystem adopts, not something the specification can impose on every consumer. An ecosystem that stores such cached values should state the contract explicitly, and may mark cached members - for example with a dedicated annotation - so that consumers which do not share the contract can still tell them apart from authoritative data.
An OO-LD instance projects to RDF through its @context and can be reconstructed from RDF. Because RDF is an unordered set of triples over a flat graph, faithful reconstruction follows a fixed contract:
@context alone.{ "<property>": {} }. The embedded object needs an explicit type only when 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); a flat scoped context for a single embedded type needs none. Where required, tooling materializes the type on export (see ).type: "array") MUST declare @container: "@set" (or "@list"): without it a single-element array returns as a scalar and violates the array type. A property that also permits a scalar (an anyOf/oneOf of 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; use @list only where order is significant, at the cost of merge and query ergonomics.@language (or @container: "@language") so multilingual instance values round-trip - distinct from x-oold-multilang-title / x-oold-multilang-description, which localize the schema's own annotations, not instance data.A datatype-coerced value round-trips by RDF value, not byte-for-byte: e.g. the JSON number 40.75 under @type: "xsd:float" becomes the canonical lexical form "4.075E1" and returns as that string. Round-trip equality for typed literals is value equality after datatype canonicalization.
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.
x-oold-iri)x-oold-iri declares the IRI of the ontology class that this schema realizes - the RDF/OWL class from an external vocabulary that gives the schema its semantic grounding. It is distinct from two related IRIs:
$id - the URL of the schema document (where to fetch it). A schema document is a retrievable artifact, not an OWL class.x-oold-instance-rdf-type - the rdf:types that instances carry on export (see ). These are stamped onto instance data; x-oold-iri describes the schema itself.In this example, the schema document is fetched from the $id URL, it realizes the ontology class schema:Person, and instances exported to RDF carry @type: schema:Person. The most common case is that x-oold-iri and the entries in x-oold-instance-rdf-type resolve to the same IRI, but they may differ - for example when a schema models a more specific subclass inline while still emitting a broader rdf:type on instances.
OO-LD-aware tooling uses x-oold-iri to anchor the schema in an ontology graph, independently of where the schema document is hosted - for example to resolve super-classes, look up ontology annotations, or generate SHACL shapes.
The schema version SHOULD be indicated by x-oold-version; a prior version MAY be indicated with x-oold-prior-version:
The version SHOULD be part of the schema's location:
https://example.org/b5203131-7321-46bb-8a11-acb3d1015840.schema.json/1.1.0.https://example.org/my-package/2.0.0/b5203131-7321-46bb-8a11-acb3d1015840.schema.json.https://raw.githubusercontent.com/MyOrg/my-package/refs/heads/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.
Schemas MAY indicate explicit backward-compatibility with x-oold-backward-compatible-with and x-oold-incompatible-with:
Schemas within a package or package repository MAY use relative URIs ([[RFC3986]] §5.1). For example, A.schema.json referenced from https://raw.githubusercontent.com/MyOrg/my-package/refs/heads/2.0.0/:
Instance documents SHOULD always use a versioned schema URL to make clear which schema version they comply with:
Upgrade APIs MAY provide automated data migration between schema (package) versions, e.g. https://example.org/upgrade/my-package/1.0.0...2.0.0.
On top of plain JSON Schema and JSON-LD, OO-LD defines a small set of extensions. This section covers the JSON-LD extensions and the JSON Schema extensions in turn.
OO-LD targets [[JSON-LD11]].
@version)OO-LD composition relies on JSON-LD 1.1 features, in particular scoped contexts: a $ref within a type: object property is reflected as a property-scoped @context (see ). Such features are unavailable to a processor running in the json-ld-1.0 processing mode.
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).
JSON-LD allows only a single keyword-IRI mapping (or more precisely, ignores all but the last mapping). There is currently no way to express that a property has two IRIs (e.g. "label": {"@id": ["schema:name", "skos:prefLabel"]}, see json-ld/json-ld.org#160). As a lightweight inline workaround, an additional context notation is provided: <property>*(*) pointing to additional @id mappings, to document alternative options or drive custom RDF generation. For the general case - more than two mappings per term, mappings a subclass can add or drop, and mappings that round-trip to a mapping set - use the structured x-oold-context notation below.
The notation can also drive data transformation and normalization. For example, a dataset in which persons and organizations report their relations in a syntactically non-interoperable way can be normalized into a consistent unified dataset (see OO-LD/oold-schema#11).
x-oold-context)The * notation above documents at most a small, fixed set of alternative @ids inline and carries no metadata about each mapping. For the general case OO-LD adds the schema-level keyword x-oold-context: an object keyed by term, where each term holds a dict keyed by the synonym IRI.
In the minimal case a term simply lists alternative IRIs, each with an empty value ({}):
Here description (primarily schema:description) also maps to rdfs:comment and skos:definition. Each bare synonym IRI defaults to predicate_id: skos:exactMatch and inherits the primary term's coercion on promotion.
Each value is itself a JSON-LD term-definition fragment (@type, @container, ...) that is promotable verbatim into @context, optionally carrying a strippable x-sssom block with mapping metadata:
Each entry is one mapping:
object_id);@type, @container, ...) that is promotable as-is, plus an optional x-sssom block;x-sssom is strippable metadata: predicate_id (default skos:exactMatch), optional confidence and mapping_justification. The subject_id is implicit (the term's primary @context IRI) and the object_id is the key.This satisfies what the * notation cannot:
schema:, bfo:, emmo:), so RDF export can prioritize a preferred namespace without an explicit tag.null removing an inherited mapping. Keys are compared as expanded IRIs, so the compact (skos:prefLabel) and full (http://www.w3.org/2004/02/skos/core#prefLabel) forms of one IRI are a single key and override correctly across mixed notations.subject_id / object_id / predicate_id / confidence / mapping_justification), so a mapping set round-trips to and from x-oold-context.To promote to @context, an OO-LD preprocessor picks the prioritized synonym (by namespace), then { "@id": <key>, ...value without x-sssom } becomes the term's definition in the real @context; the x-sssom blocks are dropped, so standard JSON-LD tools then run on a clean context.
JSON-LD 1.1 Framing reshapes a flat or arbitrarily-structured RDF graph into a specific tree layout described by a frame. An OO-LD schema already describes exactly such a tree - its properties give the nesting, its @context gives the term IRIs, a type constant (x-oold-instance-rdf-type, or a const on the type property) gives the node type, and x-oold-range gives the type of embedded or referenced objects - so an OO-LD-aware tool MAY auto-construct a frame from the schema. Framing an instance graph with that frame produces a JSON document shaped like the schema, which then validates against the same schema.
This makes an OO-LD schema bidirectional: its @context drives expansion (JSON to RDF), and the frame derived from its structure drives framing (RDF back to the schema's JSON tree). The derivation is mechanical: the schema's class type becomes the frame @type; an inlined object property becomes a nested subframe that embeds the referenced node; a reference-valued property (including one whose term is mapped with JSON-LD @reverse) becomes a subframe with @embed: @never so its targets stay IRIs, in line with the inline-versus-reference choice x-oold-range already records; and @explicit / @requireAll / @default follow from additionalProperties and required. The frame's @context is the composition of the referenced schemas' contexts.
Framing is not the only option for this transformation. When the source data lives in a triplestore or behind a SPARQL endpoint, a SPARQL CONSTRUCT query - also derivable from the schema - can select and reshape the relevant subgraph directly, including deriving reverse relations such as employees from the inverse of schema:worksFor; compacting that result with the schema's @context (and framing it where nesting is required) yields the same OO-LD instance.
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.github.io/oold-schema/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.
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.
There are two distinct localization concerns: translating a schema's own annotations, and translating a value carried by an instance.
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.
To localize a value of an instance - a translatable string in the data that should round-trip to language-tagged RDF literals - do not use the keywords above; use the standard JSON-LD mechanism. There are two equivalent JSON-LD-native ways to carry such a value, both producing the same language-tagged literals.
Explicit - model the value as an object that pairs its text with its language by aliasing text to @value and lang to @language. This form is convenient for form-based editors, where each translation is an editable row:
Compact - a language map keyed directly by language tag, via @container: @language ([[JSON-LD11]] Language Maps):
x-oold-range)JSON Schema itself supports linked data only in the form of a subobject; references to independent external objects are just URL-strings without further restrictions. To express constraints on the type of the referenced object - as in OWL and SHACL - the keyword x-oold-range is introduced (see also json-schema-org/json-schema-vocabularies#55). It takes one of three forms:
An array of IRIs, expressing a union of allowed target schemas, e.g. ["Organization.schema.json", "Person.schema.json"].
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 inside x-oold-range MUST use x-oold-ref, never $ref (see below). The single-IRI form (1) is a shorthand for { "allOf": [ { "x-oold-ref": "Organization.schema.json" } ] }:
A range subschema MAY also carry additional annotations (e.g. title, description or further x-oold-* keywords) to support tooling - for example a human-readable label for an autocomplete dropdown, or hints used when generating a SHACL shape.
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:
"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 as alice, expanded against the context's @base / @vocab."format": "iri". A compact IRI is itself a valid absolute IRI (scheme ex, path alice), so iri accepts ex:alice; choose it to additionally forbid relative references."format": "uri" or "uri-reference", where values are known not to use internationalized (non-ASCII) IRIs."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.x-oold-ref and not $refx-oold-range is a custom keyword, so a $ref placed inside it is undefined behavior for generic JSON Schema tooling ([[JSONSCHEMA]] §9.4.2). In practice the behavior is not merely undefined but inconsistent: generic reference resolvers eagerly inline such a $ref, and because x-oold-range targets can form a cyclic graph of schemas this can pull in an unbounded graph, while schema-aware bundlers instead drop it.
x-oold-ref avoids this. Generic tools only follow the standard $ref keyword, so they leave x-oold-ref untouched; OO-LD-aware tools resolve it deliberately and lazily, with cycle detection. 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.
x-oold-range (and the reverse properties below) exist so that the logical and conceptual modelling layers can be generated from the same OO-LD source instead of being maintained separately: a range constrains the type of a referenced object, which an OO-LD-aware tool emits as a SHACL property shape (sh:class / sh:node) and as an OWL property restriction. SHACL 1.2 (in progress, including Node Expressions for derived values) and OWL are the intended targets. These are generation targets, not additional validation performed by generic JSON Schema tools.
Many relations are symmetric (e.g. Organization employs Person ⇔ Person works for Organization) and users want to edit them from both sides, without storing the information twice. The keywords x-oold-reverse-properties and x-oold-reverse-required declare such a [=reverse property=], mapped with JSON-LD @reverse in the @context. (The earlier x-oold-reverse-default-properties array is deprecated: mark a reverse property shown by default with x-oold-ui-default-property on the property itself - see - which, unlike the merged array, is overridable under composition.) To make employees the reverse of organization:
employees in x-oold-reverse-properties of Organization;organization in the properties of Person;organization to a semantic property, e.g. schema:worksFor, in the @context of Person;employees with @reverse to the same property in the @context of Organization ([[JSON-LD11]] reverse properties).An OO-LD-aware implementation uses this to read and modify properties that are actually stored in another object: loading an Organization editor prepopulates employees by querying which persons work for it; storing the Organization writes it into each referenced person's organization field; and removing a person from employees removes the organization from theirs.
OO-LD schemas double as the source for auto-generated forms and views. UI intent is carried in two layers:
x-oold-ui-* vocabulary, defined here. Any form generator can honour them.x-jedison-* for jedison, the successor of json-editor - for options that do not generalize.Every keyword keeps the x- prefix, so it is a valid JSON Schema extension keyword and a valid OpenAPI 3.0 specification extension, and generic 2020-12 validators ignore it. The x-oold-ui-* keywords form their own optional dialect, described by the OO-LD UI meta-schema; the core meta-schema includes those definitions so an OO-LD schema carrying UI annotations validates in one pass.
The W3C SHACL 1.2 User Interfaces module (First Public Working Draft, 2026) describes the same concern - form and view generation - for RDF graphs. x-oold-ui-* is the portable counterpart for the physical (JSON Schema) layer: it rides on JSON Schema and therefore needs no RDF toolchain, while SHACL 1.2 UI targets a SHACL shapes graph. The two are intended to be a crosswalk rather than competing vocabularies. Candidate mappings for the x-oold-ui-* vocabulary follow (sh: = SHACL core, shui: = SHACL UI; SHACL 1.2 UI is a First Public Working Draft, so entries marked tentative may still change):
x-oold-ui-* keyword |
SHACL 1.2 UI candidate |
|---|---|
x-oold-ui-property-order |
sh:order |
x-oold-ui-property-group |
sh:group (a sh:PropertyGroup) |
x-oold-ui-widget (and format) |
shui:editor / shui:viewer with a widget class (shui:AutoCompleteEditor, shui:EnumSelectEditor, shui:DatePickerEditor, shui:BooleanEditor, shui:TextFieldEditor, shui:ImageViewer, shui:ValueTableViewer, ...) |
x-oold-ui-hint |
sh:description (help text) |
x-oold-multilang-ui-hint |
sh:description with language-tagged strings |
x-oold-ui-enum-titles |
rdfs:label on each sh:in value, rendered by shui:EnumSelectEditor |
x-oold-multilang-ui-enum-titles |
language-tagged rdfs:label on each sh:in value |
x-oold-ui-form-hidden |
suppress shui:editor (tentative) |
x-oold-ui-render-hidden |
suppress shui:viewer (tentative) |
x-oold-ui-default-property |
no direct counterpart; a shui:propertyRole / default-visibility convention (tentative) |
The OO-LD UI meta-schema MAY itself carry a JSON-LD @context recording these term identities, so the vocabulary is self-describing.
x-oold-ui-* vocabularyAll keywords apply to the (sub)schema of a single property.
| Keyword | Description |
|---|---|
x-oold-ui-widget |
Widget hint for a value whose intended widget is not a registered JSON Schema format (for example table, tabs, grid, autocomplete, textarea, checkbox, markdown, color). Registered formats (date, uri, uuid, ...) stay in format. Maps to jedison x-format. |
x-oold-ui-property-order |
Display order of this property within its object or group; lower sorts first. Maps to jedison x-categoryOrder. |
x-oold-ui-property-group |
Name of the group, tab or category this property belongs to. Maps to jedison x-category / x-propGroup. |
x-oold-ui-form-hidden |
Hide this property in the editing form. Maps to jedison x-hidden. |
x-oold-ui-render-hidden |
Hide this property in the rendered (read) view. |
x-oold-ui-enum-titles |
Human display labels for the default language, aligned positionally with enum: the Nth label is the title of the Nth enum value. For enum: ["pi", "postdoc", "phd"] the value ["Principal investigator", "Postdoc", "PhD student"] labels each option. Localize with x-oold-multilang-ui-enum-titles. Distinct from the identifier-safe code names in x-enum-varnames. Maps to jedison x-enumTitles. |
x-oold-multilang-ui-enum-titles |
BCP-47 language map of x-oold-ui-enum-titles arrays (mirrors x-oold-multilang-title); each array aligns positionally with enum. For enum: ["pi", "postdoc", "phd"]: {"en": ["Principal investigator", "Postdoc", "PhD student"], "de": ["Projektleitung", "Postdoc", "Doktorand"]}. |
x-oold-ui-hint |
Short help text shown with the field, in the default language. Localize with x-oold-multilang-ui-hint. Maps to jedison x-info. |
x-oold-multilang-ui-hint |
BCP-47 language map of the x-oold-ui-hint text (mirrors x-oold-multilang-title). |
x-oold-ui-default-property |
Whether this optional property is shown by default in generated user interfaces. Replaces the object-level defaultProperties array: a per-property boolean is overridable under composition (most-derived-wins), so a derived schema can set it false, whereas the merged array form was extend-only. |
x-enum-varnames |
Identifier-safe code names aligned positionally with enum, for code generation. For enum: ["m", "s"] the value ["metre", "second"] names each option (so a generator can emit Unit.metre instead of Unit.m). An established vendor extension (OpenAPI Generator; NSwag uses the camelCase x-enumNames). Kept as-is; distinct from the human labels in x-oold-ui-enum-titles. |
x-enum-descriptions |
Per-value descriptions aligned positionally with enum, the established companion of x-enum-varnames. For enum: ["m", "s"]: ["SI base unit of length", "SI base unit of time"]. |
The text-valued keywords have a x-oold-multilang-* variant carrying a BCP-47 language map, mirroring x-oold-multilang-title (see ): x-oold-multilang-ui-hint and x-oold-multilang-ui-enum-titles.
For enum code generation OO-LD keeps the established x-enum-varnames (identifier-safe names aligned with enum) and its companion x-enum-descriptions; these are widely supported vendor extensions (OpenAPI Generator; NSwag's x-enumNames) and are distinct from the human display labels in x-oold-ui-enum-titles.
x-oold-ui-default-property replaces the json-editor defaultProperties array (which listed the optional properties shown initially). That array is extend-only under composition: because composed schemas merge the arrays, a derived schema can add a default property but cannot switch one off. A per-property boolean is overridable - it resolves most-derived-wins (see ), so a derived schema sets it to false to hide a property a base schema showed. For the same reason x-oold-reverse-default-properties is deprecated in favour of x-oold-ui-default-property on the reverse property.
format vs x-oold-ui-widgetformat carries the widget hint when its value is a registered JSON Schema 2020-12 format (date, date-time, time, duration, email, uri, iri, uuid, ...); a validator may check it and a form generator picks the matching input. Values that are not registered formats (table, tabs, grid, autocomplete, textarea, checkbox, markdown, color, ...) are widget-only and go in x-oold-ui-widget, leaving format for validation semantics.
A modern JSON Schema 2020-12 toolchain - ajv, the json-editor / jedison built-in validator, Hyperjump, Pydantic v2, OpenAPI 3.1 - honours const and keywords placed alongside $ref, so OO-LD's composition constructs validate as written; the older assumption that such tooling silently drops them does not hold for these validators. A narrower caveat concerns UI generation rather than validation: a form generator's widget rendering of a keyword may differ from what its validator enforces - for example json-editor validates const but does not necessarily render the field as a fixed value. A consumer restricted to a Draft-4-only JSON Schema processor remains the exception, since keywords adjacent to $ref and const are only guaranteed from later drafts.
UI keywords may be embedded in the schema (inline):
{
"$schema": "https://oo-ld.github.io/oold-schema/latest/meta/oold-meta-schema.json",
"$id": "UiAnnotations.schema.json",
"@context": [
{
"@version": 1.1,
"schema": "https://schema.org/",
"name": "schema:name",
"role": "schema:jobTitle",
"homepage": { "@id": "schema:url", "@type": "@id" },
"notes": "schema:comment",
"internal_id": "schema:identifier"
}
],
"x-oold-uuid": "b1e7a0c2-2d4f-4a1e-9c3a-7f0e5d2b6a11",
"title": "Researcher",
"x-oold-multilang-title": { "en": "Researcher", "de": "Forschende Person" },
"x-oold-iri": "schema:Person",
"type": "object",
"properties": {
"name": {
"type": "string",
"title": "Name",
"x-oold-ui-default-property": true,
"x-oold-ui-property-order": 1,
"x-oold-ui-property-group": "General",
"x-oold-ui-hint": "Full name",
"x-oold-multilang-ui-hint": { "en": "Full name", "de": "Vollständiger Name" }
},
"role": {
"type": "string",
"title": "Role",
"enum": ["pi", "postdoc", "phd"],
"x-enum-varnames": ["PrincipalInvestigator", "PostDoc", "PhDStudent"],
"x-enum-descriptions": ["Leads the project", "Holds a doctorate", "Doctoral candidate"],
"x-oold-ui-enum-titles": ["Principal investigator", "Postdoc", "PhD student"],
"x-oold-multilang-ui-enum-titles": { "en": ["Principal investigator", "Postdoc", "PhD student"], "de": ["Projektleitung", "Postdoc", "Doktorand"] },
"x-oold-ui-property-order": 2,
"x-oold-ui-property-group": "General"
},
"homepage": {
"type": "string",
"title": "Homepage",
"format": "uri",
"x-oold-ui-property-group": "Contact"
},
"notes": {
"type": "string",
"title": "Notes",
"x-oold-ui-widget": "markdown",
"x-oold-ui-property-group": "Contact"
},
"internal_id": {
"type": "string",
"title": "Internal id",
"x-oold-ui-form-hidden": true
}
}
}
or applied by an overlay - a separate document that patches a schema without editing it, following the OpenAPI Overlay 1.1.0 model. Overlays are a general schema-patching mechanism: the update actions can inject any keywords (semantics, constraints or presentation), and applying x-oold-ui-* annotations is one use case - useful when the schema is generated or owned elsewhere, or when one schema needs different presentation in different contexts. An overlay lists actions, each selecting nodes with an RFC 9535 JSONPath target and merging keys via update (or removing them via remove):
{
"overlay": "1.0.0",
"info": {
"title": "Researcher admin overlay",
"version": "1.0.0",
"description": "Applies presentation-only x-oold-ui-* keywords to Researcher without editing the schema. An overlay is a general schema-patching mechanism (OpenAPI Overlay 1.1.0); UI annotation is one use case."
},
"extends": "./UiAnnotations.schema.json",
"actions": [
{
"target": "$.properties.internal_id",
"description": "Show the internal id for admins.",
"update": { "x-oold-ui-form-hidden": false }
},
{
"target": "$.properties.notes",
"description": "Render notes as a plain textarea instead of markdown.",
"update": { "x-oold-ui-widget": "textarea" }
},
{
"target": "$.properties.role",
"description": "Drop the render-time grouping for a flat admin form.",
"remove": false,
"update": { "x-oold-ui-property-group": "Identity" }
}
]
}
The vendor keywords are documented by their respective projects: jedison's x-jedison-* (see germanbisurgi/jedison#58 and the overlay proposal #59) and, for schemas coming from OpenSemanticLab, the server-side x-osl-* keywords. Migrating a legacy OpenSemanticWorld schema to these keywords is covered in the migration guide.
An OO-LD schema carries its semantics in the top-level @context and, for the RDF type of instances, in x-oold-instance-rdf-type. How those reach a consumer depends only on which keywords the consumer tolerates. The native form is preferred; the alternatives below are mechanically generated from it, so the OO-LD document remains the single source and every form yields the same RDF.
@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.@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. That draft requires references inside these keywords not to be dereferenced automatically, consistent with the x-oold-ref rule (see ). The mapping is reversible, so such an export can be read back into an OO-LD schema.title / description annotations the model also reads.Worked examples of each tier, including the per-class OpenAPI 3.0 mapping, are given in the guide (see Delivery to OpenAPI, MCP and LLM tooling).
OO-LD adds keywords on top of JSON Schema 2020-12. All OO-LD-proprietary keywords are prefixed with x-oold- so they are valid JSON Schema extension keywords and, at the same time, valid OpenAPI 3.0 Specification Extensions (OpenAPI 3.0 rejects unprefixed custom keywords in a Schema object). The only non-prefixed OO-LD-specific entry is @context, which is a JSON-LD keyword and cannot be renamed.
The OO-LD dialect is described by a meta-schema ([[OOLD-META]]). It extends the standard 2020-12 meta-schema and adds the syntax of the x-oold-* keywords, so an OO-LD schema can be validated as an OO-LD schema. The meta-schema declares its vocabularies via $vocabulary: the seven standard 2020-12 vocabularies are re-listed as required (they are not inherited through $ref, [[JSONSCHEMA]] §8.1.2.2), and the OO-LD vocabulary is declared optional (false) so that generic 2020-12 validators still process OO-LD schemas instead of refusing them.
Declaring a vocabulary does not make a validator execute keyword behavior; that is supplied by OO-LD-aware tooling (e.g. the oold library). The meta-schema only validates that x-oold-* keywords are well-formed and provides a machine-readable description for each. The x-oold-* keywords are:
| Keyword | Description |
|---|---|
x-oold-context |
Extended term mappings (synonyms): an object keyed by term, each holding a dict keyed by synonym IRI whose value is a JSON-LD term-definition fragment plus an optional strippable x-sssom block. Supports more than two mappings per term, override under composition (most-derived-wins; null removes), prefix-driven ontology-family prioritization, and SSSOM round-trip. Promoted into @context by OO-LD-aware tooling; see the 'Term mappings and synonyms' section. |
x-oold-uuid |
Stable UUID identifying this schema across versions and locations. |
x-oold-version |
Semantic version of this schema. |
x-oold-prior-version |
Identifier or version of the immediately preceding schema version. |
x-oold-backward-compatible-with |
URI of a prior schema version this schema is backward-compatible with. |
x-oold-incompatible-with |
URI of a prior schema version this schema is NOT compatible with. |
x-oold-iri |
Ontology IRI (or compact IRI) denoting the class described by this schema. |
x-oold-instance-rdf-type |
The rdf:type(s) carried by instances of this schema, as a list of IRIs (e.g. ["schema:Person"]). OO-LD tooling materializes these as @type when exporting an instance to JSON-LD / RDF. |
x-oold-ref |
Reference to another OO-LD schema. Use x-oold-ref (not the standard $ref) for references that appear inside OO-LD custom keywords such as x-oold-range: there a plain $ref would be eagerly - and, for cyclic schema graphs, dangerously - dereferenced by generic JSON-Schema bundlers (the behaviour is undefined per Core section 9.4.2). Keep using the standard $ref for ordinary schema composition (allOf, properties, $defs), which bundlers are expected to resolve. x-oold-ref is resolved only by OO-LD-aware tools, lazily and with cycle handling. |
x-oold-range |
Type constraint on the target of an IRI-valued property: an IRI string, an array of IRIs, or an OO-LD subschema (using x-oold-ref for references). See the 'Range of properties' section. |
x-oold-multilang-title |
Language map of translated title values keyed by BCP-47 language code. |
x-oold-multilang-description |
Language map of translated description values keyed by BCP-47 language code. |
x-oold-reverse-properties |
Properties stored on the related object but editable from this side, mapped via JSON-LD @reverse. |
x-oold-reverse-required |
Names of reverse properties that are required. |
x-oold-reverse-default-properties |
Deprecated. Names of reverse properties shown by default in generated user interfaces. Like the object-level defaultProperties array this is extend-only under composition; prefer a per-reverse-property x-oold-ui-default-property boolean, which is overridable. |
| Slot | File extension | Media type | RFC 6906 profile | Description |
|---|---|---|---|---|
| schema | *.schema.json | application/oold-schema+json |
- | Full OO-LD schema |
| schema | *.schema.json | application/oold-schema+json |
oold-schema#bundled | Full OO-LD schema with all $ref and remote context bundled |
| schema | *.schema.json | application/oold-schema+json |
http://www.w3.org/ns/json-ld#context |
Only the JSON-LD context |
| schema | *.schema.json | application/ld+json |
- | Only the JSON-LD context |
| schema | *.schema.json | application/schema+json |
- | Only the JSON Schema schema |
| data | *.data.json | application/oold-schema-instance+json |
- | Full OO-LD instance |
| data | *.data.json | application/ld+json |
http://www.w3.org/ns/json-ld#* |
Full OO-LD instance; the profiles defined in [[JSON-LD11]] IANA considerations apply |
| data | *.data.json | application/json |
- | Only the JSON data |
Both the security considerations of [[JSON-LD11]] (§C) and of [[JSONSCHEMA]] (§13) apply. In particular, 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.
The following defined terms are used in this specification: [=OO-LD=], [=OO-LD schema=], [=OO-LD instance=], [=remote context=], [=resolved schema=], [=range=], [=reverse property=].