A recent IFCJSON-Team discussion around the uses of JSON-LD Framing led me to make a pedagogical demo based on bot. I figured I’d post it in the open in case it helps others.
Modeling a Simple Two Storey Building
Let’s model a simple two storey building using bot and JSON-LD. We’ll assign two rooms to each storey.
{"@context":[{"bot":"https://w3id.org/bot#",
"hasStorey":{"@type":"@id", "@id":"bot:hasStorey"},
"hasSpace":{"@type":"@id", "@id":"bot:hasSpace"}},
{"@base":"http://myproject.org#"}],
"@graph":[
{"@id":"mybuilding", "@type":"bot:Building",
"hasStorey":["level-1", "level-2"]},
{"@id":"level-1", "@type":"bot:Storey",
"hasSpace":["room-1.1", "room-1.2"]},
{"@id":"level-2", "@type":"bot:Storey",
"hasSpace":["room-2.1", "room-2.2"]},
{"@id":"room-1.1", "@type":"bot:Space"},
{"@id":"room-1.2", "@type":"bot:Space"},
{"@id":"room-2.1", "@type":"bot:Space"},
{"@id":"room-2.2", "@type":"bot:Space"}
]
}
The graph we’ve defined is simple enough to be read and understood directly. Unfortunately, all buildings, storeys, and spaces are defined in a flat list, belying their hierarchical structure. It would be nice if our JSON-LD document could be reordered to reflect the containment relationships inherent in the model. This is a use case JSON-LD Framing solves well. Let’s see how.
Framing The Building Top-Down
Every JSON-LD Frame is a request, intended for a JSON-LD Frame Processor, that instructs it how we would like the underlying JSON-LD graph (here, our building model) presented. Every Frame defines the requested node types (e.g., bot:Building, bot:Storey, bot:Space), along with a description of the "shape" we’d like those types to take. In our case, we’d like to hoist the graph into a tree reflecting the hierarchical decomposition of the building. Here’s a Frame to do that:
{
"@context": {
"@vocab": "https://w3id.org/bot#",
"@base": "http://myproject.org#"
},
"@type": "Building",
"hasStorey": {
"@type": "Storey",
"hasSpace": {
"@type": "Space"
}
}
}
Applying this Frame to the original graph returns a view onto the graph that reflects the intended containment relationships:
{
"@context": {
"@vocab": "https://w3id.org/bot#",
"@base": "http://myproject.org#"
},
"@id": "mybuilding", "@type": "Building",
"hasStorey": [
{
"@id": "level-1","@type": "Storey",
"hasSpace": [
{"@id": "room-1.1", "@type": "Space"},
{"@id": "room-1.2","@type": "Space"}
]
},
{
"@id": "level-2", "@type": "Storey",
"hasSpace": [
{"@id": "room-2.1", "@type": "Space"},
{"@id": "room-2.2","@type": "Space"}
]
}
]
}
We didn’t need to change any part of our building model to build this view. The frame just helped us highlight the relationships we care about - the spatial decomposition of our Building by Storey and Space.
Framing The Building Bottom-Up
Other frames can operate on the same graph model to highlight other node types or relationships. For example, let’s say we wanted a schedule of all the Spaces in our Buildings. Here’s one possible frame:
{
"@context": {
"@vocab": "https://w3id.org/bot#",
"@base": "http://myproject.org#",
"inStorey": {
"@reverse": "hasSpace"
},
"inBuilding": {
"@reverse": "hasStorey"
}
},
"@type": "Space",
"inStorey": {
"@type": "Storey",
"@embed": "@always",
"@explicit": true
},
"inBuilding": {
"@type": "Building",
"@embed": "@always",
"@explicit": true
}
}
}
And the result when applied to the model:
{
"@context": {
"@vocab": "https://w3id.org/bot#",
"@base": "http://myproject.org#",
"inStorey": {
"@reverse": "hasSpace"
},
"inBuilding": {
"@reverse": "hasStorey"
}
},
"@graph": [
{
"@id": "room-1.1",
"inStorey": {
"@id": "level-1",
"inBuilding": {"@id": "mybuilding","@type": "Building"},
"@type": "Storey"
},
"@type": "Space"
},
{
"@id": "room-1.2",
"inStorey": {
"@id": "level-1",
"inBuilding": {"@id": "mybuilding", "@type": "Building"},
"@type": "Storey"
},
"@type": "Space"
},
{
"@id": "room-2.1",
"inStorey": {
"@id": "level-2",
"inBuilding": { "@id": "mybuilding", "@type": "Building"},
"@type": "Storey"
},
"@type": "Space"
},
{
"@id": "room-2.2",
"inStorey": {
"@id": "level-2",
"inBuilding": { "@id": "mybuilding", "@type": "Building"},
"@type": "Storey"
},
"@type": "Space"
}
]
}
By changing the frame only, we’ve managed to flip the building containment hierarchy inside-out. Now we see a list of every Space, along with references to its containing Storey and Building. It’s straightforward to build asset-specific schedules from a format like this.
Wrap-Up
Intermediary frame shapes are possible too. The richer the building model, the more frames we can apply. Given the prevalance of breakdown structures within the construction industry, JSON-LD Frames offer a simple and flexible strategy for defining tailored "views" onto asset ontologies, digital twins, and building information models.