Open community to develop schemas and tools to link object-oriented programming with linked data & the semantic web.
We don't reinvent standards - we compose them. OO-LD as a composition is what we're bringing into open standardization.
The abbreviation OO-LD (and the placement of the hyphen) is intentional: it highlights the object-oriented focus while echoing JSON-LD.
The short version:
- One source, many outputs - the same schema validates JSON data and generates RDF, code (e.g. Pydantic), data-entry UIs, and OpenAPI specs.
- Standards-aligned, not standards-locked - every document is at once a valid [JSON Schema 2020-12] (https://json-schema.org/specification) and a valid JSON-LD 1.1 context; no fork, no new language.
- Reuses the tooling you already have - works with existing JSON Schema and JSON-LD libraries; OO-LD-specific extensions are safely ignored by both.
- Linked data without the learning curve - web-retrievable, semantically interoperable schemas without first becoming an RDF expert.
Modern applications need their data to do two jobs at once:
- Be valid - does this document have the right shape and types?
- Mean something - what real-world concept does each field actually refer to?
JSON Schema solves (1). JSON-LD solves (2). Today, teams who need both maintain two parallel files that drift apart - and JSON-LD assumes a level of semantic-web expertise that most application developers don't have.
OO-LD merges both into a single, referenceable, versioned document so one source describes shape and meaning together. Object-oriented developers get interoperable linked data without first having to become RDF experts.
What is JSON Schema?
A widely-used standard for describing the structure of JSON documents - which fields exist, their types, which are required, and how they nest. Used by OpenAPI, form generators, and most modern validation libraries. Spec: json-schema.org (Draft 2020-12)
What is JSON-LD?
A W3C standard that adds semantic meaning to JSON by mapping each field to a globally unique identifier (an IRI). A JSON-LD document can be losslessly converted to RDF triples and joined with other linked data on the web. Spec: www.w3.org/TR/json-ld11
What is Linked Data / RDF?
Linked Data is the practice of identifying things with web URLs so data from different
sources can be joined. RDF (Resource Description Framework) is the underlying data
model - every fact is a triple of (subject, predicate, object). Together they make
data interoperable across organizations and tools.
Intro: www.w3.org/wiki/LinkedData
An OO-LD document is a JSON Schema with an embedded @context. The mechanism is
surprisingly simple:
- JSON Schema validators ignore unknown top-level keys, including
@context. - JSON-LD processors ignore keys they don't recognize, including
properties,type: "object",required, and so on.
The same file passes through both toolchains, each seeing only what it cares about. One document becomes the source of truth for validation, semantics, code, and UI:
flowchart LR
Doc["📄 OO-LD Document<br/><sub>JSON Schema + @context</sub>"]
Doc --> V["JSON Schema<br/>Validator"]
Doc --> J["JSON-LD<br/>Processor"]
Doc --> C["Code<br/>Generator"]
Doc --> U["Form / UI<br/>Renderer"]
V --> V1["✅ Validated instances"]
J --> J1["🔗 RDF triples<br/><sub>joins with linked data</sub>"]
C --> C1["🐍 Pydantic / dataclasses<br/><sub>typed objects in code</sub>"]
U --> U1["📝 HTML forms<br/><sub>auto-generated UI</sub>"]
classDef doc fill:#eef,stroke:#446,stroke-width:2px;
classDef out fill:#efe,stroke:#464;
class Doc doc;
class V1,J1,C1,U1 out;
| Output | Produced by | From which part of the document |
|---|---|---|
| Validated instances | JSON Schema validator | type, properties, required, … |
| RDF triples | JSON-LD processor | @context + matching data instance |
| Generated code (Pydantic, dataclasses) | OO-LD code generator | full schema + context |
| Generated forms / UI | JSON-Schema form renderer | properties, title, description |
How OO-LD applies the JSON-LD rules: in OO-LD, the
@contextin an OO-LD instance document references the remote@context("@context": "https://example.com/MySchema.schema.json") that lives in the OO-LD schema, rather than defining it inline. Every referencing instance inherits all semantics automatically - instances stay as plain JSON, with no per-document mapping boilerplate. The@contextin the OO-LD schema is not to be applied to the content of that document but to the instances alone. OO-LD schemas are never to be processed as JSON-LD documents themselves.
What is @context?
A JSON-LD construct that maps short JSON keys (e.g. name) to globally
unique identifiers (e.g. http://schema.org/name). It's how a JSON document
gains semantic meaning without changing how the data itself looks. See the inversion
note above for how OO-LD places it in the schema rather than the data instance.
Why doesn't this break either standard?
Both specs are deliberately permissive about unknown keywords:
- JSON Schema 2020-12 §6.5: unknown keywords are not errors; validators MUST ignore them unless they opt in via vocabularies.
- JSON-LD 1.1 §4.4: terms not defined in the active context are dropped during expansion, not flagged as errors.
OO-LD lives in the intersection where each spec is silent about the other's vocabulary. No spec changes are required.
What does "Object-Oriented" mean here?
OO-LD schemas can extend, compose, and specialize each other using standard JSON Schema
mechanisms ($ref, allOf) that line up with RDF class
hierarchies. An Employee schema can inherit from Person, and
both structural and semantic definitions are inherited together. See the
Inheritance and Composition example below.
Here's the smallest possible OO-LD schema (Person.schema.json):
{
"@context": {
"schema": "http://schema.org/",
"name": "schema:name"
},
"$id": "https://example.com/Person.schema.json",
"title": "Person",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "First and Last name"
}
}
}This file is simultaneously a JSON Schema (defines structure) and a JSON-LD context (provides semantics). Notice how @context maps the name property to schema:name, enabling both validation and RDF generation from the same source.
- UI and RDF generation: OO-LD Playground - Interactive examples with UI and RDF generation
- Code and RDF generation: Python Playground - Advanced examples with code generation
- Full Tutorial - Step-by-step guide with working examples
OO-LD schemas extend each other using standard JSON Schema mechanisms ($ref, allOf),
and the semantic mappings stack automatically. Here's Person extended into Employee.
Base schema - Person.schema.json:
{
"@context": {
"schema": "http://schema.org/",
"name": "schema:name"
},
"$id": "https://example.com/Person.schema.json",
"title": "Person",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "First and Last name"
}
}
}Derived schema - Employee.schema.json:
{
"@context": [
"https://example.com/Person.schema.json",
{
"schema": "http://schema.org/",
"jobTitle": "schema:jobTitle",
"employer": {
"@id": "schema:worksFor",
"@type": "@id"
}
}
],
"$id": "https://example.com/Employee.schema.json",
"title": "Employee",
"type": "object",
"allOf": [
{ "$ref": "https://example.com/Person.schema.json" }
],
"properties": {
"jobTitle": {
"type": "string",
"description": "Job title"
},
"employer": {
"type": "string",
"format": "iri",
"description": "IRI of the employing organization"
}
},
"required": ["jobTitle"]
}Two inheritance mechanisms work in parallel:
| Layer | Mechanism | Effect |
|---|---|---|
| Structure (JSON Schema) | allOf + $ref to parent schema |
Employee must satisfy all of Person's constraints plus its own |
| Semantics (JSON-LD) | @context array referencing parent schema |
Employee inherits Person's term mappings, then adds its own |
A data instance - alice.json:
{
"@context": "https://example.com/Employee.schema.json",
"$schema": "https://example.com/Employee.schema.json",
"name": "Alice",
"jobTitle": "Engineer",
"employer": "https://example.com/companies/acme"
}Instances stay as plain JSON. They reference the schema once - via both @context
(for semantics) and $schema (for validation) - and inherit everything from it.
No per-instance @type, no @id boilerplate required.
This single instance simultaneously:
1. Validates against both schemas. Person's constraint (name as string) and
Employee's (jobTitle required, employer as IRI) all check out.
2. Expands to RDF triples via the inherited @context:
@prefix schema: <http://schema.org/> .
_:b0 schema:name "Alice" ;
schema:jobTitle "Engineer" ;
schema:worksFor <https://example.com/companies/acme> .3. Generates a Python class hierarchy that mirrors the schema inheritance:
# Generated by oold-python
from pydantic import BaseModel, ConfigDict
from typing import Optional
class Person(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"@context": {
"schema": "http://schema.org/",
"name": "schema:name"
}
}
)
name: Optional[str] = None
"""First and Last name"""
class Employee(Person): # ← real subclass, not flat duplication
model_config = ConfigDict(
json_schema_extra={
"@context": [
"https://example.com/Person.schema.json",
{
"schema": "http://schema.org/",
"jobTitle": "schema:jobTitle",
"employer": {
"@id": "schema:worksFor",
"@type": "@id"
}
}
]
}
)
jobTitle: str
"""Job title"""
employer: Optional[str] = None
"""IRI of the employing organization"""How does @context inheritance work?
JSON-LD 1.1 allows @context to be an array. Each entry is merged
left-to-right, with later entries overriding earlier ones. When an entry is a string
URL, the JSON-LD processor fetches that document and merges its @context.
Because every OO-LD schema embeds its @context at the top level, pointing
at Person.schema.json from inside Employee.schema.json pulls
in Person's term mappings before Employee's own are applied.
How does JSON Schema inheritance work?
allOf requires the instance to validate against every schema in its array.
Combined with $ref, it's the standard JSON Schema idiom for "this schema
extends that one":
"allOf": [{ "$ref": "https://example.com/Person.schema.json" }]
JSON Schema doesn't have a dedicated extends keyword - allOf + $ref
is the convention OpenAPI, Pydantic, and most code generators recognize as inheritance.
Because the meaning of each field lives in the schema, an instance references a versioned schema URL - pinning exactly which schema version, and therefore which ontology mapping, it complies with. You can remap terms or fix a semantic binding in a new schema version without rewriting existing data; migration tooling handles the upgrade.
How versioning & identity work
- Every schema has a stable, resolvable
$idand SHOULD carry anx-oold-uuid(a UUID that identifies the schema across renames) and anx-oold-version(SemVer). - Instances reference a versioned schema URL via both
@contextand$schema- e.g.https://example.com/my-package/1.0.0/Person.schema.json. - Schemas can declare compatibility explicitly with
x-oold-prior-version,backward-compatible-with, andincompatible-with. - This is why instances carry no inline
@typeor ontology IRIs: the versioned schema owns the semantic mapping, so data stays stable while the mapping can evolve.
Spec: OO-LD Versioning
OO-LD targets teams who need interoperable, semantically meaningful data without a dedicated semantic-web specialist on staff - from application developers to research labs to public administration. One schema serves validation, RDF, code, and UI at once:
- LLM-Structured Output - JSON Schema is the contract LLMs use for structured
generation. Because an OO-LD schema is a JSON Schema, you can hand it directly to LLM
APIs and frameworks like LangChain
- and get back data that is both validated and semantically annotated, ready for RDF or a knowledge graph.
- APIs & Code Generation - Generate typed classes (Pydantic dataclasses) and OpenAPI specifications from the same schema, with semantic context preserved through the whole stack (e.g. via FastAPI).
- Auto-generated User Interfaces - Render data-entry forms and graph editors straight from the schema - no hand-written UI code - including autocomplete dropdowns backed by linked-data sources.
- Research Data Management - Describe experiments, samples, and instruments once and get validation, RDF export, and data-entry forms together. OpenSemanticLab builds its LIMS, ELN, and knowledge-base platform on OO-LD, integrating with research-data infrastructures such as NFDI.
- Public Administration & Civic-Tech - Build interoperable data structures that carry their meaning with them, making linked-data interoperability practical for teams that aren't RDF experts.
OO-LD's core bet: don't invent a new language - a single document is at once a valid JSON Schema and a referenceable JSON-LD context, so structure and semantics stay in one source, with no separate modelling language and no generate-then-sync step. Here's how that compares to the common alternatives (a ✅ is always the favourable outcome):
| Approach | Validates plain JSON | RDF semantics | Both from one source (no generation/sync step) | No new language | Reuses existing tooling |
|---|---|---|---|---|---|
| OO-LD | ✅ | ✅ | ✅ | ✅ | ✅ JSON Schema and JSON-LD tools |
| JSON Schema alone | ✅ | ❌ | ➖ structure only | ✅ | ✅ |
| JSON-LD alone | ❌ (no structural rules) | ✅ | ➖ semantics only | ✅ | ✅ |
| LinkML | ✅ via generated JSON Schema | ✅ via generated context | ❌ separate schema + context | ❌ custom YAML language | Own toolchain + generators |
| SHACL / OWL | ❌ RDF only | ✅ | ➖ RDF only | ❌ | RDF tooling only |
OO-LD does add a small set of optional x-oold-* annotation keywords (range, reverse
properties, UI hints, ...) that generic JSON Schema 2020-12 validators ignore. These extend
the two base standards rather than replace them, and are kept only where no existing
standard fits - the goal is to interoperate through generated bridges (x-jsonld-* for
OpenAPI/MCP, SHACL for validation, OWL for reasoning, bidirectional LinkML) rather than a
walled garden.
When another tool may fit better:
- Formal reasoning / inference over your data → OWL
- Validating data that's already RDF-native → SHACL
- A high-level modeling language with many export targets → LinkML - which can itself generate OO-LD schemas (JSON Schema + JSON-LD context), so the two are complementary rather than exclusive.
For the full landscape (AAS, SAMM, TreeLDR, SmartDataModels, dlite, NOMAD, and more), see the Related Work table in the specification.
OO-LD is stabilizing toward a 1.0 specification. The core approach is already proven in production by OpenSemanticLab and several proof-of-concept implementations; current work hardens both the specification and the Python reference implementation. Everything is open source (Apache-2.0) and versioned with SemVer.
✅ Available today
- The OO-LD schema pattern on JSON Schema 2020-12 + JSON-LD 1.1
- Python library (prototype): code generation, RDF import/export, graph-object binding
- Interactive playgrounds for UI, RDF, and Python code generation
- In production use within OpenSemanticLab
🚧 In progress - toward v1.0
- Finalized OO-LD 1.0 specification with documented best practices
- Production-ready Python reference implementation (stable API, >90% test coverage)
- Offline schema bundler
- Schema and meta-schema validation
- LLM structured-output integration for common frameworks
- Schema-versioning and migration tooling
- Automated form / UI generation and a graph viewer
📋 Planned - sustainability & governance
- Community structure with a steering committee
- Package registry for community-contributed schemas
- Tutorial video series and webinars
- Submission to a W3C Community Group for open standardization
| You want to… | Go to |
|---|---|
| Try OO-LD in your browser (UI + RDF from a schema) | Playground (YAML) |
| Generate code (Python / Pydantic) from a schema | Playground (Python) · oold-python |
| Use OO-LD in a Python project (codegen, RDF import/export, graph-object binding) | oold-python |
| Auto-generate data-entry forms / UI | Playground (YAML) |
| Visualize or edit a semantic graph | interactive-semantic-graph |
| Use schemas for LLM structured output | Hand the schema to your LLM API - example: [OSW Chatbot] (https://github.com/opensemanticworld/osw-chatbot) |
| Describe semantic workflows | AWL Schema · AWL Playground |
| Run a full data-management platform | OpenSemanticLab |
| Read the formal specification | OO-LD Specification |
- OO-LD Specification - Complete schema specification and examples
- oold-python - Python code generator and utilities
- Playground (YAML) - Interactive UI and RDF generation
- Playground (Python) - Try code generation online
- AWL Schema - Semantic workflow descriptions
- OpenSemanticLab - Research data management framework
- OpenSemanticWorld-Packages - Schema repository
- OpenSemanticWorld - Schema registry
- Battery Knowledge Graph - Scientific metadata using OO-LD
- OSW Chatbot - LLM integration examples
Questions, ideas and design discussion are welcome - for now all in the issue tracker (one searchable place while the community is small):
- Question (usage, tooling, spec interpretation) - open an issue with the
questionlabel. - Open-ended discussion / proposal - open an issue with the
discussionlabel. - Bug or feature - open a regular issue in the relevant repository.
- Contribute - pull requests are welcome; for larger changes, open a
discussionissue first.
If demand grows we'll add GitHub Discussions and/or a chat.
The generic, domain-independent OO-LD framework - the specification and its reference implementation - is funded by the German Federal Ministry of Research, Technology and Space (BMFTR) through the Prototype Fund (funding code / Förderkennzeichen 16IS26S16).
The application of OO-LD to materials science is funded by the European Union’s Horizon Europe research and innovation programme under grant agreement No. 101293545 (MaterialsCommons). This grant covers a domain-specific extension only.



