Skip to main content

The canonical JSON schema

A key-by-key reference for canonical JSON. Every example here was produced by actually running the tool on a bundled building.

What is omitted

A key with no value is not emitted. koyu, h, slab, t, edge, attrs, line and the rest appear only if the source wrote them. Empty blocks (assets, polygons, columns, zones, areas, openings, segs) are not emitted either.

Attribute values are numbers if they have numeric form, strings otherwise. underground is emitted as 1 only when true; air is emitted as true only when true.

Top level

The key order is fixed.

KeyPresentContent
formatalwaysthe version of this format itself; currently "koyu-canonical/1.0"
koyuonly with a version declarationthe language version, passed through
nameif name was writtenthe name of the building
unitalwayscurrently "mm" only
gridalways{ "X": [coords…], "Y": [coords…] } — the names X1.. are implicit
levelsalwaysname → { z, h?, slab?, underground? }; keys in collation order
assetsif declaredname → { kind, attrs? }; keys in collation order
polygonsif declaredpath → [[x, y], …]; keys in collation order
columnsif declaredan array, in declaration order
zonesif declaredpath → { attrs? }; keys in collation order
spacesalwayspath → space; keys in path collation order
boundariesalwaysan array; lexicographic by between, ties by canonical content

grid

"grid": { "X": [0, 3600, 7200], "Y": [0, 4500] }

Only the coordinate arrays. Grid names are implicitly X1, X2, … from the front, so they are not spelled.

levels

"levels": {
"B1": { "z": -5100, "h": 4200, "slab": 900, "underground": 1 },
"L1": { "z": 0, "h": 3600, "slab": 600 }
}
KeyMeaning
zFL height in mm. Always present
hceiling height in mm
slabfloor construction depth in mm
undergroundthe declaration that a level is below ground. Never inferred from a negative z — emitted as 1 only when written

assets

"assets": {
"AD1": { "kind": "door", "attrs": { "h": 2400, "name": "自動ドア", "style": "auto", "w": 1800 } }
}

A type of joinery. kind is door or window. Openings reach it through ref.

polygons

"polygons": { "/site": [[-2600, -7000], [38000, -7000], [38000, 19600], [2000, 21000], [-2600, 15000]] }

A given, and the one geometry written into the source. The vertex list is geometry (cyclic) and is never reordered.

columns

"columns": [
{ "size": 900, "levels": ["B2", "B1", "L1", "L2", "L3", "L4", "L5", "L6"] },
{ "size": 800, "levels": ["L7", "L8", "L9", "L10", "L11", "L12", "L13"] }
]
KeyMeaning
sizesection width in mm
ddepth in mm. Omitted when it equals size
levelsthe levels the column stands on
x / ythe grids it targets. Omit for all grids. Ordered by grid order (x:X2,X1 and x:X1,X2 are the same composition)
attrsattributes

This is the one array that is never sorted. Two columns never stand on the same intersection and the earlier declaration wins, so declaration order is the composition itself.

zones

"zones": { "/L3/A": { "attrs": { "name": "Aタイプ", "use": "exclusive" } } }

A zone carries attributes only. No region, no type.

spaces

"/L1/s1": {
"type": "shop",
"at": [
["X1", "Y1-4600", "X3", "Y2"],
["X3", "Y1-4600", "X4", "Y1"]
],
"attrs": { "floor": "モルタル", "name": "店舗1", "use": "rentable" },
"areas": [
{ "at": ["X1", "Y1-4600", "X2", "Y1-2600"], "attrs": { "floor": "タイル", "name": "土間" } }
]
}
KeyPresentContent
typealwaysthe type of the space
levelonly when explicitemitted only when the level differs from the first path segment (a maisonette, say). The default is omitted
atif there is a regionfour grid names. A flat quadruple for a single rectangle, an array of quadruples for several, sorted by canonical content
attrsif there are attributeskeys in collation order
areasif area was writtenan array of { at, attrs? } in canonical content order

The quadruple is [X start, Y start, X end, Y end]. A reversed notation (X2..X1) is normalised to ascending coordinates.

boundaries

{
"between": ["/home/hall1", "/home/ldk"],
"a": "/home/ldk",
"kind": "wall",
"t": 120,
"attrs": { "spec": "LGS" },
"openings": [
{
"kind": "door", "ref": "SD1", "w": 800, "h": 2000,
"at": 0.5, "edge": "E", "hinge": "S", "swing": "b",
"attrs": { "name": "片引き戸", "style": "sliding" }
}
]
}
KeyPresentContent
betweenalwaysthe two paths in ascending order. This is the identity of the relation
aalwaysthe written direction — the space written first. edge and swing are read from that side. Without it, the swing cannot be recovered from JSON alone
kindalwayswall / open / stair / shaft / void
tif writtenwall thickness in mm
aironly when truetrue. Something that does not enclose (a rail, a fence)
edgeif writtenN / E / S / W — narrows the segments to one face seen from a
lineif writtenthe endpoint pair of a drawn line, as grid words, in ascending resolved coordinates
attrsif there are attributesspec, fire, h, …
openingsif there are openingscanonical content order
segsif there are segscanonical content order

The top height of an air:1 boundary is emitted as an attribute.

{
"between": ["/home/hall2", "/home/void"],
"a": "/home/void",
"kind": "wall", "t": 120, "air": true,
"attrs": { "h": 1100, "spec": "手すり" }
}

A boundary with a drawn line.

{
"between": ["/L1/load", "/out"],
"a": "/L1/load",
"kind": "wall", "t": 300,
"line": ["X19-4200,Y12", "X19,Y12-2100"],
"attrs": { "spec": "RC" }
}

A segment has no direction, so the endpoint pair is canonicalised to ascending resolved (x, then y). The spelling stays exactly the grid reference that was written; only the order swaps.

Default boundaries do not appear here. Touching spaces default to a wall, but canonical JSON holds only the written composition.

openings

KeyPresentContent
kindalwaysdoor / window
refwhen an asset is usedthe asset name
walwayswidth in mm
hif writtenheight in mm
atalwaysa number for a ratio, a string for a grid reference. Unwritten it is 0.5
edgeif writtenN / E / S / W
hingeif writtenthe hinge side
swingif writtenthe side it opens into, a / b
attrsif there are attributesname, style, … Attributes inherited from an asset are expanded and emitted too

segs

"segs": [
{ "w": 3600, "at": 0.75, "attrs": { "spec": "ガラスパーティション" } }
]
KeyPresentContent
walwayswidth in mm
atalwaysa number for a ratio, a string for a grid reference
edgeif writtenN / E / S / W
attrsif there are attributesan interval override such as spec

A seg is an uncounted segment — it appears in no area and no graph, and carries only an override over an interval.

Neighbouring pages