Skip to content

About

SAREF ontologies in LinkML

Resources

Code of conduct

Contributing

Stars

11 stars

Watchers

2 watching

Forks

Repository files navigation

CI License Discord Playground built with LinkML-Scala

SAREF-LinkML

SAREF is ETSI's reference ontology for the Internet of Things. This repository has SAREF core and four of its extensions written as LinkML schemas. We also publish SAREF SHACL shapes, RDFS, and JSON Schemas generated from LinkML.

SAREF is published as OWL, which works well for reasoning and Semantic Web tools, but does not help with validation (constraints) or with data formats other than RDF. LinkML solves that: it is a modelling language that works across formats. You write a schema in LinkML, and it generates SHACL, RDFS, JSON Schema, Frictionless table schemas, GraphQL, ER diagrams, and code for several languages.

We use SAREF-LinkML in our work to:

  • Guide agents when aligning data to SAREF.
  • Validate SAREF data in RDF with SHACL.
  • Express SAREF data in JSON and validate it with JSON Schema.
  • Draw ER diagrams of SAREF classes and their relationships.
  • Reason about SAREF with "light" semantics in RDFS.

Important

This is an unofficial, community conversion. It is not endorsed by, affiliated with, or maintained by ETSI, and it is not a normative representation of SAREF. Please report problems with these schemas here, not to ETSI.

Releases

Every release contains the LinkML schemas plus SHACL shapes, RDFS, and JSON Schema already generated from them. If you only want the artifacts, you can download them from the releases page without needing any LinkML tooling.

Tags are v<SAREF core version>-<date>, for example v4.1.1-2026-08-25. The first half says which upstream ontology the conversion targets, the second says which conversion it is, so a fix to the conversion alone still produces a higher version. Dated releases go out automatically on Mondays, and only when something has actually changed. There is also a dev prerelease, rebuilt on every push to main.

Usage

LinkML schemas

They are in schema/:

If an extension that you need is not here, please open an issue.

Classes in LinkML are written in a YAML format. For example, the Sensor class looks like this:

Sensor:
  class_uri: saref:Sensor
  title: Sensor
  description: A device designed to observe and measure one or more properties
    or states of one or more features of interest.
  mixins:
    - Device
  slots:
    - observes
  slot_usage:
    observes:
      required: true

Generating SHACL, RDFS, JSON Schema, and other formats

Grab the five files from schema/. Then, we recommend using LinkML-Scala, which is a single binary with no runtime dependencies (see the installation instructions).

Generate a JSON Schema for SAREF4ENER:

linkml-scala generate json-schema --to saref4ener.schema.json schema/saref4ener.yaml

Generate SHACL shapes, so you can validate RDF data with any SHACL engine:

linkml-scala generate shacl --open --to shapes.ttl schema/saref-core.yaml

Run linkml-scala --help for more generators and options.

You can also play with the schemas in the in-browser playground, or use use them in Python, Java, or JavaScript.

Using SAREF for JSON

To make a SAREF JSON document, you need to pick a class that will be the root of the document (tree_root). SAREF itself does not say what that is, so you have to add one. examples/ has two small hand-written schemas that do this, alongside JSON data that matches them:

  • device-catalog.yaml – a catalogue of sensors in an installation, the properties they observe, and the units those come in.
  • observation-log.yaml – a batch of readings that refer to a sensor catalogue by IRIs.

A reading then looks like this:

{
  "has_timestamp": ["2026-08-25T09:00:00Z"],
  "made_by": ["ex:thermostat-hallway"],
  "observes": ["ex:indoor-air-temperature"],
  "has_result": [{ "has_value": [21.4], "is_measured_in": ["qudt-unit:DEG_C"] }]
}

Those single-element arrays are arrays on purpose. SAREF declares these slots multivalued, and slot_usage may only narrow a slot, never change its shape: turning a list into a scalar would make data that is valid against the parent class invalid against the child. So the example schemas write maximum_cardinality: 1, which says "at most one entry" without breaking that rule. See the note on cardinality below.

To check that the JSON really does match:

pip install jsonschema neverblink-linkml
python checks/check-json.py --schema examples/observation-log.yaml --data examples/observation-log.json

How it works and limitations

The conversion from SAREF's original in OWL to LinkML is fully automated using the bin/owl2linkml.py script. It uses the translation rules defined in mapping/mapping_table.yaml.

Tests

We use ETSI's SAREF examples to test the generated SHACL shapes.

  1. The generated RDFS must match the source ontology. checks/check-rdfs.py compares the class hierarchy and property coverage of the generated RDFS against the original Turtle, and reports anything lost that the mapping table does not account for.
  2. The generated SHACL must be able to validate ETSI's examples. checks/check-examples.py validates ETSI's own examples against the generated SHACL shapes, with some exceptions (some examples are not fully compliant or incomplete).
  3. The LinkML schema must be valid under linkml-scala validate --strict.
  4. The hand-written JSON examples must validate against the generated JSON Schema. checks/check-json.py generates a JSON Schema from each schema in examples/ and validates the JSON file next to it.

To run the checks locally:

pip install -r requirements.txt
linkml-scala generate shacl --open --to build/shapes.ttl schema/saref-core.yaml
linkml-scala generate rdfs --to build/rdfs.ttl schema/saref-core.yaml
python checks/check-rdfs.py --rdfs build/rdfs.ttl --schema schema/saref-core.yaml \
  --source source/SAREFCore/saref.ttl
python checks/check-examples.py --shapes build/shapes.ttl --schema schema/saref-core.yaml \
  --examples source/SAREFCore/examples --mode open
python checks/check-json.py --schema examples/device-catalog.yaml --data examples/device-catalog.json

Most of ETSI's examples needed a small edit before they would validate, usually because they use a term without ever saying what type it is, or because they predate a cardinality the ontology now requires. Every edit is noted down: source/README.md lists what was changed.

Limitations

  • owl:minCardinality 1 becomes required: true, and owl:minCardinality 0 is skipped. An upper bound (max 1, cardinality 1) becomes maximum_cardinality: 1 in slot_usage. Only a bound of exactly 1 is written today; larger ones are dropped and reported, though nothing in SAREF has one.
  • Two restrictions are read as closed, stricter than the axiom: owl:someValuesFrom X becomes required: true and range: X, and owl:hasValue becomes a closed enum. owl:allValuesFrom also becomes a range.
  • By default all slots are multivalued: true, constraints restrict that per class basis. Exception: owl:FunctionalProperty sets multivalued: false on the slot itself, schema-wide.
  • When there are multiple restrictions on the same slot, the WIDEST is taken (e.g. saref:represents). The loser is dropped whole, not just the key that lost.
  • An owl:DatatypeProperty that declares rdfs:range rdfs:Literal becomes Any (linkml:Any).

Contributing and support

Bug reports, questions, and pull requests are welcome. If a class or slot came out wrong, an issue with the offending term and what you expected is the most useful thing you can send.

The files in schema/ are generated, and CI overwrites them. To fix the translation, edit the mapping table or the converter. CONTRIBUTING.md explains how to set up the environment, how to regenerate the schemas, how to run the checks, and how to add an extension or move to a new SAREF version.

This project follows a Code of Conduct.

You can also join our Discord to ask questions.

License and provenance

The LinkML schemas here are a conversion of ETSI's SAREF ontologies from OWL/Turtle into LinkML. The source ontologies are Copyright 2019 ETSI and licensed under the BSD 3-Clause License. The same license applies to this repository, and its terms carry over to the converted schemas. Class and slot definitions, labels, and descriptions are derived from the ETSI sources. The LinkML modelling decisions, the converter, and the tooling are the work of this project's contributors. See LICENSE.

"SAREF" is used here descriptively, to identify the source ontology.

Maintainers

This project is developed and maintained by NeverBlink. For inquiries, write to us at contact@neverblink.eu.


This work has been supported by the HEDGE-IoT project grant number 101136216 funded by the European Commission as part of the Horizon Europe Framework Programme. However, views and opinions expressed are those of the authors only and do not necessarily reflect those of the European Union or the European Climate, Infrastructure and Environment Executive Agency. Neither the European Union nor the granting authority can be held responsible for them.

About

SAREF ontologies in LinkML

Resources

Code of conduct

Contributing

Stars

11 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages