Using JSON-LD
See also: https://linkml.io/linkml/intro/tutorial04.html
This how-to guide walks through some of the basics of working with JSON-LD and LinkML
About JSON-LD
JSON-LD is a way of working with JSON documents that are also RDF documents. JSON-LD can provide a powerful bridge between “developer-friendly” JSON serializations and Linked Data frameworks.
Well-constructed JSON-LD can be easy to work with in “traditional” software and data science environments, while retaining benefits of RDF and a direct conversion to RDF. However, there are also pitfalls to be aware of.
Two key concepts to be aware of that make JSON-LD work for you:
Contexts
Framing
A full description of these is outside the scope of this guide, but we will provide some practical examples
JSON-LD Example
Consider a simple data graph containing two person objects, grouped into a ‘container’ object:
@prefix schema: <http://schema.org/> .
@prefix personinfo: <https://w3id.org/linkml/examples/personinfo/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<https://orcid.org/1234> a schema:Person ;
schema:name "Clark Kent" ;
schema:telephone "555-555-5555" ;
personinfo:age 33 .
<https://orcid.org/4567> a schema:Person ;
schema:name "Lois Lane" ;
personinfo:age 34 .
[] a personinfo:Container ;
personinfo:persons <https://orcid.org/1234>,
<https://orcid.org/4567> .
We can use a standard JSON-LD compliant tool (for example, Apache Jena) to convert this to JSON-LD, which may look something like this:
{
"@graph" : [ {
"@id" : "_:b0",
"@type" : "personinfo:Container",
"persons" : [ "https://orcid.org/4567", "https://orcid.org/1234" ]
}, {
"@id" : "https://orcid.org/1234",
"@type" : "schema:Person",
"name" : "Clark Kent",
"telephone" : "555-555-5555",
"personinfo:age" : 33
}, {
"@id" : "https://orcid.org/4567",
"@type" : "schema:Person",
"name" : "Lois Lane",
"personinfo:age" : 34
} ],
"@context" : {
"age" : {
"@id" : "https://w3id.org/linkml/examples/personinfo/age",
"@type" : "http://www.w3.org/2001/XMLSchema#integer"
},
"telephone" : {
"@id" : "http://schema.org/telephone"
},
"name" : {
"@id" : "http://schema.org/name"
},
"persons" : {
"@id" : "https://w3id.org/linkml/examples/personinfo/persons",
"@type" : "@id"
},
"schema" : "http://schema.org/",
"xsd" : "http://www.w3.org/2001/XMLSchema#",
"personinfo" : "https://w3id.org/linkml/examples/personinfo/"
}
}
Hurray! We have a JSON form of our RDF graph. Developers can work with this format using familiar JSON parsers, not requiring any special RDF libraries. It can be stored in a Mongo Database, it can be queried using jq, ….
Hold your horses! Before handing this JSON to our fellow developers, let’s take a closer look.
First you will see fields such as:
@id
@type
This violates common idioms with JSON documents, where fields are usually ‘key-friendly’. As well as being unusual-looking, this structure could actually hinder development and even break some tooling.
Thankfully, we don’t have to give such ugly JSON to our fellow developers. In fact there are multiple ways to represent the same RDF as a JSON-LD document. We can make our JSON much more idiomatic through the use of JSON-LD contexts.
Context
Let’s provide an initial context for our JSON-LD
{
"@context": {
"ORCID": "https://orcid.org/",
"linkml": "https://w3id.org/linkml/",
"personinfo": "https://w3id.org/linkml/examples/personinfo/",
"schema": "http://schema.org/",
"@vocab": "https://w3id.org/linkml/examples/personinfo/",
"persons": {
"@type": "@id"
},
"age": {
"@type": "xsd:integer"
},
"full_name": {
"@id": "schema:name"
},
"type": "@type",
"id": "@id",
"phone": {
"@id": "schema:telephone"
},
"Person": {
"@id": "schema:Person"
}
}
}
Don’t worry about authoring these contexts for now (in fact, as we will see later, these can be autogenerated from LinkML schemas).
Using the JSON-LD playground we can make JSON that is approaching something more idiomatic:
{
"@context": {
"ORCID": "https://orcid.org/",
"linkml": "https://w3id.org/linkml/",
"personinfo": "https://w3id.org/linkml/examples/personinfo/",
"schema": "http://schema.org/",
"@vocab": "https://w3id.org/linkml/examples/personinfo/",
"persons": {
"@type": "@id"
},
"age": {
"@type": "xsd:integer"
},
"full_name": {
"@id": "schema:name"
},
"type": "@type",
"id": "@id",
"phone": {
"@id": "schema:telephone"
},
"Person": {
"@id": "schema:Person"
}
},
"@graph": [
{
"id": "_:b0",
"type": "Container",
"persons": [
"ORCID:4567",
"ORCID:1234"
]
},
{
"id": "ORCID:1234",
"type": "Person",
"full_name": "Clark Kent",
"phone": "555-555-5555",
"personinfo:age": 33
},
{
"id": "ORCID:4567",
"type": "Person",
"full_name": "Lois Lane",
"personinfo:age": 34
}
]
}
Ignore the @context
blob at the top - that can easily be maksed or imported over the web. We now have a list of Person objects
Considerations
Being able to customize the structure of JSON is flexible and powerful. However, this power should be wielded carefully.
Let’s consider the organization SemanticsRUs
. This organization has
an internal information ecosystem constructed on Linked Data
standards. Data is stored in triplestores, and software that
manipulates data uses libraries such as rdflib or Jena. This
organization can happily consume any RDF serialization format
(RDF/XML, turtle, n-triples, …). It can also handle JSON-LD
documents, and they don’t care whether the JSON-LD is expanded or
compacted. These all get converted to the same internal RDF graph
representation. This organization may use a shape language like SHACL
or OWL to enforce conformance of RDF graphs to a particular structure,
but they don’t care about the serialization (except perhaps for performance reasons).
In fact SemanticsRUs don’t even need JSON-LD at all, but they may find it useful for exchanging data with the broader information ecosystem including mere mortal developers who will only consume JSON.
Now consider another organization JsonFTW
, who have a more
traditional information system. They might rely heavily on exchange of
YAML/JSON documents, perhaps storing these in a Mongo database. They
may also have some kind of enterprise data model or data models, with
mappings from JSON to those models. Or potentially SQL databases or
other noSQL databases. It’s likely this organization makes heavy use
of JSON-Schema to ensure documents are structured in expected ways,
allowing reliable and predictable software to be built.
Both organizations have valid ways of dealing with data, with respective strengths and limitations, and presumably they have optimized their approaches to the niche they occupy.
Now let’s imagine a developer, MonicaTripleton leaves SemanticsRUs and joins JsonFTW. She manages to persuade her new developer colleagues to adopt some linked data practices, starting with use of JSON-LD. This all goes well, with the JSON-LD adopting appropriate contexts and framing such that existing JSON-Schemas continue to function, and the developers also start gaining some of the benefits of RDF.
How imagine Monica leaves, and JohnnyEvangelist takes her place. Johnny is a born again Linked Data fanatic. He doesn’t adopt the practices put in place by Monica, and instead starts exchanging JSON-LD documents that are expanded or otherwise don’t conform to internal framing/contexts. Things start breaking, but Johnny