-
Notifications
You must be signed in to change notification settings - Fork 1
JSON LD
JSON-LD is a serialisation of RDF, like turtle, but based around the JSON data format.
- The JSON-LD spec has introductory material and examples. We will cover a much smaller set of features in this document.
- https://json-ld.org/
- Google's SEO (search engine optimisation) documentation has a section on structured data with many examples of how including JSON-LD within a website's HTML can be used to make Google and other search engines show special results.
- Google's docs mention structured data for Datasets which include the CSV on the Web standard (see CSV on the Web).
- Google have a tutorial for adding strutured data to a webpage.
- https://sketch.zazuko.com/ is a useful tool for visualising RDF (including JSON-LD).
- The JSON-LD Playground is good for playing with JSON-LD and viewing the equivalent turtle.
- Google's rich results test for testing strutured data within a webpage.
JSON-LD defines some special keywords to represent RDF.
-
@idis a special keyword used to specify the URI of a resource. - Predicates and objects are specified through further JSON key-value pairs.
The following turtle can be represented as JSON-LD in this way:
<http://example.org#Ross> <http://example.org#knows> <http://example.org#Alex> .{
"@id": "http://example.org#Ross",
"http://example.org#knows": {
"@id": "http://example.org#Alex"
}
}The type of a resource can be indicated by the @type keyword.
<http://example.org#Ross> a <http://example.org#Person> .{
"@id": "http://example.org#Ross",
"@type": "http://example.org#Person"
}Multiple objects can be written with a JSON array:
@prefix ex: <http://example.org#> .
ex:Ross ex:knows ex:Alex, ex:Andrew .{
"@id": "http://example.org#Ross",
"http://example.org#knows": [
{
"@id": "http://example.org#Alex"
},
{
"@id": "http://example.org#Andrew"
}
]
}Blank nodes are represented by omitting the @id keyword:
@prefix ex: <http://example.org#> .
ex:Ross ex:knows [ ex:name "Alex"@en ] .Literals are represented using the @value keyword. A typed literal's type is indicated by the @type keyword.
A date literal can be represented like this:
@prefix ex: <http://example.org#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ex:Ross ex:birthday "1900-01-01"^^xsd:date .{
"@id": "http://example.org#Ross",
"http://example.org#birthday": {
"@value": "1900-01-01",
"@type": "http://www.w3.org/2001/XMLSchema#date"
}
}Language strings are similar. The language of a literal can be represented by the @language keyword (while omitting the @type keyword.)
@prefix ex: <http://example.org#> .
ex:Q102438 a ex:Book ;
ex:name "Harry Potter and the Philosopher's Stone"@en,
"Harri Potter a Maen yr Athronydd"@cy,
"Harry Potter à l'école des sorciers"@fr,
"Harry Potter und der Stein der Weisen"@de,
"Harry Potter y la piedra filosofal"@es ;
.{
"@id": "http://example.org#Q102438",
"http://example.org#name": [
{
"@value": "Harry Potter and the Philosopher's Stone",
"@language": "en"
},
{
"@value": "Harri Potter a Maen yr Athronydd",
"@language": "cy"
},
{
"@value": "Harry Potter à l'école des sorciers",
"@language": "fr"
},
{
"@value": "Harry Potter und der Stein der Weisen",
"@language": "de"
},
{
"@value": "Harry Potter y la piedra filosofal",
"@language": "es"
}
]
}The @context keyword is similar to the concept of providing prefixes in turtle or SPARQL, though is a bit more powerful. A context can be used to alias URIs, potentially giving an author of JSON-LD the ability to not have to use any of the @id, @value or @language keywords (which some developers think are a bit weird to work with).
This is an example of the CSVW context. (See CSV on the Web.)
Consider the following triple:
<http://example.org#Ross> <http://example.org#knows> <http://example.org#Alex> .Without a context, a fully expanded JSON-LD document would look like:
{
"@id": "http://example.org#Ross",
"http://example.org#knows": {
"@id": "http://example.org#Alex"
}
}We may define a @context which includes a prefix ex. This can be used throughout the JSON-LD similarly to how it would be in turtle.
{
"@context": {
"ex": "http://example.org#"
},
"@id": "ex:Ross",
"ex:knows": {
"@id": "ex:Alex"
}
}The context can also map full terms to URIs. The following context includes foaf as a prefix and includes a mapping for the term knows:
- The
@idforknowsis set tofoaf:knows, meaning it will be interpreted asfoaf:knowswhen interpreted as RDF, - The
@typeforknowsis set to@id, which indicates the value associated withknowsshould be interpreted as a URI instead of a literal.
{
"@context": {
"ex": "http://example.org#",
"foaf": "http://xmlns.com/foaf/0.1/",
"knows": {
"@id": "foaf:knows",
"@type": "@id"
}
},
"@id": "ex:Ross",
"knows": "ex:Alex"
}@prefix ex: <http://example.org#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
ex:Ross foaf:knows ex:Alex .Contexts can be used to turn "easier" looking JSON into full RDF. You could imagine an API or some software producing JSON which looks as follows:
{
"book_id": "Q102438",
"title_en": "Harry Potter and the Philosopher's Stone",
"title_cy": "Harri Potter a Maen yr Athronydd",
"title_fr": "Harry Potter à l'école des sorciers",
"title_de": "Harry Potter und der Stein der Weisen",
"title_es": "Harry Potter y la piedra filosofal"
}This JSON doesn't contain any of the @ keywords such as @id, @type, @language or @value which might be expected in an expanded JSON-LD document. Also, no URLs appear in the JSON.
We can add semantics and additional meaning to the JSON by including a context. With the following context, the JSON document is equivalent the he previous RDF example for multiple language strings.
{
"@context": {
"@base": "http://example.org/",
"book_id": {"@id": "@id"},
"title_en": {"@id": "ex:title", "@language": "en"},
"title_cy": {"@id": "ex:title", "@language": "cy"},
"title_fr": {"@id": "ex:title", "@language": "fr"},
"title_de": {"@id": "ex:title", "@language": "de"},
"title_es": {"@id": "ex:title", "@language": "es"}
},
"book_id": "Q102438",
"title_en": "Harry Potter and the Philosopher's Stone",
"title_cy": "Harri Potter a Maen yr Athronydd",
"title_fr": "Harry Potter à l'école des sorciers",
"title_de": "Harry Potter und der Stein der Weisen",
"title_es": "Harry Potter y la piedra filosofal"
}We could serve the above inline context as a file at the URL http://ross-book-shop.co.uk/api/context, and then reference the URL - compacting the JSON document further.
{
"@context": "http://ross-book-shop.co.uk/api/context",
"book_id": "Q102438",
"title_en": "Harry Potter and the Philosopher's Stone",
"title_cy": "Harri Potter a Maen yr Athronydd",
"title_fr": "Harry Potter à l'école des sorciers",
"title_de": "Harry Potter und der Stein der Weisen",
"title_es": "Harry Potter y la piedra filosofal"
}Consider the triple Ross knows Alex:
@prefix ex: <http://example.org#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
ex:Ross foaf:knows ex:Alex .Sometimes it is more convienient to produce a JSON where the object of the triple is "above" the subject in the JSON hierarchy. In this case, we can use the @reverse keyword to flip the positions of subject and object.
The following JSON-LD results in the above triple.
{
"@context": {
"ex": "http://example.org#",
"foaf": "http://xmlns.com/foaf/0.1/",
"isKnownBy": {
"@reverse": "foaf:knows",
"@type": "@id"
}
},
"@id": "ex:Alex",
"isKnownBy": "ex:Ross"
}The @nest keyword helps with nested JSON structures. The following is equivalent to the previous language string example, despite the JSON structure being different.
{
"@context": {
"@base": "http://example.org/",
"ex": {"@id": "http://example.org/"},
"book_id": {"@id": "@id"},
"title": "@nest",
"en": {"@id": "ex:title", "@language": "en", "@nest": "title"},
"cy": {"@id": "ex:title", "@language": "cy", "@nest": "title"},
"fr": {"@id": "ex:title", "@language": "fr", "@nest": "title"},
"de": {"@id": "ex:title", "@language": "de", "@nest": "title"},
"es": {"@id": "ex:title", "@language": "es", "@nest": "title"}
},
"book_id": "Q102438",
"title": {
"en": "Harry Potter and the Philosopher's Stone",
"cy": "Harri Potter a Maen yr Athronydd",
"fr": "Harry Potter à l'école des sorciers",
"de": "Harry Potter und der Stein der Weisen",
"es": "Harry Potter y la piedra filosofal"
}
}If you inspect a page on GOV.UK and look at the HTML, you will usually find some HTML tags with <script type="application/ld+json">. This is used to embed JSON-LD structured data in a webpage and helps with search engine optimisation (see Google's docs).
The following JSON-LD was taken from GOV.UK's UK bank holidays page. It uses the schema.org context which can be viewed here. Try writing equivalent RDF in turtle.
{
"@context": "http://schema.org",
"@type": "Article",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://www.gov.uk/bank-holidays"
},
"name": "UK bank holidays",
"datePublished": "2016-01-26T13:04:36.000+00:00",
"dateModified": "2021-12-06T13:26:54.000+00:00",
"text": "Find out when bank holidays are in England, Wales, Scotland and Northern Ireland - including past and future bank holidays",
"publisher": {
"@type": "Organization",
"name": "GOV.UK",
"url": "https://www.gov.uk",
"logo": {
"@type": "ImageObject",
"url": "https://www.gov.uk/assets/frontend/govuk_publishing_components/govuk-logo-73b5a4056ffe9988d02c728b56fe9fe7f90bb822322a5f6183ccbb92a99b019a.png"
}
},
"image": [
"https://www.gov.uk/assets/frontend/govuk_publishing_components/govuk-schema-placeholder-1x1-bf9e64d759af6dfd93bede8168f3087a329f405b382aff36747db0db4b7b23e9.png",
"https://www.gov.uk/assets/frontend/govuk_publishing_components/govuk-schema-placeholder-4x3-13093f053c15f613acd827aff27cac83d3fab452947cbcae4c7b706dadf2f7f2.png",
"https://www.gov.uk/assets/frontend/govuk_publishing_components/govuk-schema-placeholder-16x9-4233cd42671827e266e284c4d5ae68fb600bd9f9e35dda663ccabbc2b6ab7ec3.png"
],
"author": {
"@type": "Organization",
"name": "Government Digital Service",
"url": "https://www.gov.uk/government/organisations/government-digital-service"
},
"about": [
{
"@context": "http://schema.org",
"@type": "Thing",
"sameAs": "https://www.gov.uk/employment/time-off"
}
],
"headLine": "UK bank holidays",
"description": "Find out when bank holidays are in England, Wales, Scotland and Northern Ireland - including past and future bank holidays"
}
{ "@id": "http://example.org#Ross", "http://example.org#knows": { // no "@id" here "http://example.org#name": { "@value": "Alex", "@language": "en" } } }