2025-05-17
If you ever need to represent knowledge in a way that's easy for both humans and machines to understand, while working seamlessly with existing JSON tools and libraries, JSON-LD has you covered. JSON-LD, short for JavaScript Object Notation for Linked Data, allows you to express knowledge as a graph in any domain. A good example is how Google is utilizing Linked Data to very precisely list information, such as recipes, book descriptions, events, products, and more.
One great feature of JSON-LD is its built-in support for compacting
and expanding
the representations of knowledge.
To show how these concepts work in practice I will illustrate it with an example from Star Wars. Given that we are talking about compacting and expanding, let's represent the characters in the iconic trash compactor scene from Star Wars using JSON-LD. For those unfamiliar with the scene, it starts with the protagonists, Luke, Han, Leia and Chewbacca falling into a trash compactor during an escape. As the walls begin to close in to crush the garbage, with the characters stuck in it, they frantically search for a way to stop the process. In the end they manage to deactivate the compactor by contacting the two droids, C-3PO and R2-D2, who manage to shut it down just in time.
We'll start by describing the characters who fall into the compactor in a compacted JSON-LD format. (If you want to follow along and experiment yourself, JSON-LD Playground is a great online tool for trying out Linked Data!)
Here's the compacted JSON-LD:
{
"@context": {
"schema": "http://schema.org/",
"name": "schema:name",
"member": "schema:member",
"Person": "schema:Person",
"url": "schema:url",
"description": "schema:description",
"birthPlace": "schema:birthPlace"
},
"@id": "http://example.org/starwars-ld",
"name": "The Star Wars Trash Compactor Scene",
"member": [
{
"@type": "Person",
"name": "Han Solo",
"url": "https://en.wikipedia.org/wiki/Han_Solo",
"description": "A roguish smuggler and captain of the Millennium Falcon.",
"birthPlace": "Corellia"
},
{
"@type": "Person",
"name": "Luke Skywalker",
"url": "https://en.wikipedia.org/wiki/Luke_Skywalker",
"description": "A farm boy from Tatooine thrust into the fight against the Empire.",
"birthPlace": "Polis Massa"
},
{
"@type": "Person",
"name": "Leia Organa",
"url": "https://en.wikipedia.org/wiki/Princess_Leia",
"description": "A princess of Alderaan and an important member of the Rebel Alliance.",
"birthPlace": "Polis Massa"
},
{
"@type": "Person",
"name": "Chewbacca",
"url": "https://en.wikipedia.org/wiki/Chewbacca",
"description": "A loyal Wookiee warrior and co-pilot of the Millennium Falcon.",
"birthPlace": "Kashyyyk"
}
]
}
This representation, which also is a valid JSON, gives the names, a small description and the birthplace for each of the characters. One place where it differs from a regular JSON representation is that it uses the @context section to link to a common terminology in Schema.org. This allows for software that can make use of such common vocabularies to precisely interpret the exact meaning in our description, without the need to guess and potentially hallucinate its meaning.
In order to unambiguously represent each concept Linked Data tend to use full URIs, such as http://schema.org/name
, but reading full URIs each time would be quite exhausting for a human reader. Instead, in this compacted form, the context and prefixes it makes easy for human readers to go understand the JSON-LD file, without ever losing the context.
For machines however, it can be easier to interpret the information that every identifier is written out fully, such as http://schema.org/name
as opposed to name
. For this we can expand
our JSON-LD document.
The expanded version is as follows:
[
{
"@id": "http://example.org/starwars-ld",
"http://schema.org/member": [
{
"@type": [
"http://schema.org/Person"
],
"http://schema.org/birthPlace": [
{
"@value": "Corellia"
}
],
"http://schema.org/description": [
{
"@value": "A charming smuggler and captain of the Millennium Falcon."
}
],
"http://schema.org/name": [
{
"@value": "Han Solo"
}
],
"http://schema.org/url": [
{
"@value": "https://en.wikipedia.org/wiki/Han_Solo"
}
]
},
{
"@type": [
"http://schema.org/Person"
],
"http://schema.org/birthPlace": [
{
"@value": "Polis Massa"
}
],
"http://schema.org/description": [
{
"@value": "A young Jedi learning the ways of the Force."
}
],
"http://schema.org/name": [
{
"@value": "Luke Skywalker"
}
],
"http://schema.org/url": [
{
"@value": "https://en.wikipedia.org/wiki/Luke_Skywalker"
}
]
},
{
"@type": [
"http://schema.org/Person"
],
"http://schema.org/birthPlace": [
{
"@value": "Polis Massa"
}
],
"http://schema.org/description": [
{
"@value": "A fearless princess and leader of the Rebel Alliance."
}
],
"http://schema.org/name": [
{
"@value": "Leia Organa"
}
],
"http://schema.org/url": [
{
"@value": "https://en.wikipedia.org/wiki/Princess_Leia"
}
]
},
{
"@type": [
"http://schema.org/Person"
],
"http://schema.org/birthPlace": [
{
"@value": "Kashyyyk"
}
],
"http://schema.org/description": [
{
"@value": "A loyal Wookiee warrior and Han Solo's co-pilot."
}
],
"http://schema.org/name": [
{
"@value": "Chewbacca"
}
],
"http://schema.org/url": [
{
"@value": "https://en.wikipedia.org/wiki/Chewbacca"
}
]
}
],
"http://schema.org/name": [
{
"@value": "The Star Wars Trash Compactor Scene"
}
]
}
]
Much like for our heroes in the movie, from a software's perspective, it is good that things are expanded. Any software can now precisely see the exact URI links, such as http://schema.org/Person
, without doing a lookup in the context and the prefixes each time. Of course for us humans it looks very verbose, but we can always compact it back, though hopefully after our heroes have escaped.
As bonus, JSON-LD also have a representation that is flattened
. This collects all entities into a single list and gives each one an explicit @id.
This is useful when you want everything neatly indexed and separated:
Flattened:
{
"@context": {
"schema": "http://schema.org/",
"name": "schema:name",
"member": "schema:member",
"Person": "schema:Person",
"url": "schema:url",
"description": "schema:description",
"birthPlace": "schema:birthPlace"
},
"@graph": [
{
"@id": "_:b0",
"@type": "Person",
"birthPlace": "Corellia",
"description": "A charming smuggler and captain of the Millennium Falcon.",
"name": "Han Solo",
"url": "https://en.wikipedia.org/wiki/Han_Solo"
},
{
"@id": "_:b1",
"@type": "Person",
"birthPlace": "Polis Massa",
"description": "A young Jedi learning the ways of the Force.",
"name": "Luke Skywalker",
"url": "https://en.wikipedia.org/wiki/Luke_Skywalker"
},
{
"@id": "_:b2",
"@type": "Person",
"birthPlace": "Polis Massa",
"description": "A fearless princess and leader of the Rebel Alliance.",
"name": "Leia Organa",
"url": "https://en.wikipedia.org/wiki/Princess_Leia"
},
{
"@id": "_:b3",
"@type": "Person",
"birthPlace": "Kashyyyk",
"description": "A loyal Wookiee warrior and Han Solo's co-pilot.",
"name": "Chewbacca",
"url": "https://en.wikipedia.org/wiki/Chewbacca"
},
{
"@id": "http://example.org/starwars-ld",
"member": [
{
"@id": "_:b0"
},
{
"@id": "_:b1"
},
{
"@id": "_:b2"
},
{
"@id": "_:b3"
}
],
"name": "The Star Wars Trash Compactor Scene"
}
]
}
Here each character gets their own node with an ID, and the relationships ("members of the scene") are made by pointing to these IDs.
JSON-LD offers a versatile toolkit for compacting, expanding, or flattening data, enabling you to organize knowledge with clarity and precision for both humans and machines! Just as the Star Wars heroes narrowly escaped the trash compactor, well-structured data can save your systems from collapsing under the weight of complexity.