CityJSON vs CityGML

Both hold the same kind of 3D city model: buildings, their parts, attributes and levels of detail. CityGML is the OGC standard written in XML. CityJSON writes a subset of the CityGML 3.0 data model in JSON, and is an OGC standard too. It lists every vertex once and points to it by number, so the same buildings take far less space.

Sample Tower_v2.gmlCityGML 2.0

5,334 characters
<bldg:Building gml:id="BLD_B-101">
  <gen:stringAttribute name="+layer">
    <gen:value>UNIT</gen:value>
  </gen:stringAttribute>
  <bldg:boundedBy>
    <bldg:GroundSurface gml:id="GroundSurface_18">
      <bldg:lod2MultiSurface>
        <gml:MultiSurface>
          <gml:surfaceMember>
            <gml:Polygon>
              <gml:exterior>
                <gml:LinearRing>
                  <gml:posList srsDimension="3">26 0 0 26 8 0 36 8 0 26 0 0</gml:posList>
                </gml:LinearRing>
              </gml:exterior>
            </gml:Polygon>
          </gml:surfaceMember>
          <gml:surfaceMember>
            <gml:Polygon>
              <gml:exterior>

First 20 of 137 lines

The corners of each polygon are written out in full, so a corner shared by several faces is written once for each of them.

Sample Tower.city.jsonCityJSON 2.0

521 characters
"BLD_B-101": {
  "type": "Building",
  "geometry": [{
    "type": "MultiSurface",
    "lod": "2",
    "boundaries": [[[24,27,26]], [[24,26,25]], [[28,29,30]], …],
    "semantics": {
      "surfaces": [{"type": "GroundSurface"},
                   {"type": "RoofSurface"},
                   {"type": "WallSurface"}],
      "values": [0,0,1,1,2,2,2,2,2,2,2,2]
    }
  }],
  "attributes": {"layer": "UNIT"}
}

"vertices": [ …, [26000,0,0], [36000,0,0],
              [36000,8000,0], [26000,8000,0], … ],
"transform": {"scale": [0.001,0.001,0.001],
              "translate": [0.0,0.0,0.0]}

The whole building, formatted

One list of vertices as integers, with a scale and an offset in transform. Each face points into that list by number.
The whole Sample Tower, 8 buildings
CityGML 2.0
44 KB
CityGML 3.0
44 KB
CityJSON 2.0
4 KB

At a glance

CityGMLCityJSON
EncodingXML with GML: GML 3.1.1 in CityGML 2.0, GML 3.2 in CityGML 3.0JSON
Data modelCityGML 2.0 or CityGML 3.0A subset of CityGML 3.0
StandardOGC. CityGML 2.0 in 2012; CityGML 3.0 in 2021, with its GML encoding in 2023OGC. CityJSON 2.0
CoordinatesWritten out in every polygonOne list of integer vertices with a transform; faces point to them by number
Levels of detailLOD 0 to 4 in 2.0, LOD 0 to 3 in 3.0, in the element name such as lod2MultiSurfaceLOD 0 to 3, as text such as "2" or "2.2"
Storeys and unitsCityGML 3.0 only: Storey and BuildingUnitBuildingStorey and BuildingUnit
Textures and colorsAppearance moduleappearance with materials and textures
Schema checkXSD schemas published by OGCJSON schemas, checked with the official validator cjval
File.gml.city.json, or .city.jsonl with one feature per line

The CityJSON project reports files seven times smaller than CityGML on average. In the sample above, the CityJSON file is about a tenth of the size.

Which one to use

If the project or the software that receives the model names a format and a version, deliver that one. CityGML 2.0 and 3.0 are different files: 3.0 adds storeys, building units and interiors at every level, and drops LOD 4.

CityJSON is smaller and is plain JSON, so any programming language reads it without an XML library.

You do not have to choose before converting. Insula3D writes CityGML 2.0, CityGML 3.0 and CityJSON 2.0 from the same conversion and checks each file it writes.

What differs between the files Insula3D writes

Storeys
With the Storey · 3.0 · CityJSON role, CityGML 3.0 and CityJSON get storeys under the building. CityGML 2.0 has no storey, so there the value goes out as an attribute.
LOD 4
Exists only in CityGML 2.0. When a layer uses LOD 4, the Output window asks which LOD to write in CityJSON and CityGML 3.0 instead: LOD3 or LOD2.
Units and rooms
Building units and constructive elements are new in CityGML 3.0 and exist in CityJSON. CityGML 2.0 has rooms only at LOD 4. Where 2.0 has no place for an object, Insula3D writes it as BuildingPart and counts it.
Addresses
CityGML writes the address as xAL. CityJSON writes its own address field.
Checks
Each CityGML file is checked against the official XSD schemas. After the run, cjval and val3dity check the CityJSON.

Questions

Is CityJSON an OGC standard?

Yes. CityJSON 2.0 is an OGC standard. It encodes a subset of the CityGML 3.0 data model.

Can CityJSON store LOD 2.2?

Yes. In CityJSON the LOD is text: a single digit, or a value such as "2.2" for the refined levels from TU Delft. In CityGML the level is part of the element name, such as lod2MultiSurface. See CityGML LOD explained.

Which CityJSON version does Insula3D write?

CityJSON 2.0, next to CityGML 2.0 and 3.0 from the same conversion.

Can Insula3D open CityJSON and CityGML files?

Yes. Open a CityJSON file or a CityGML 1.0, 2.0 or 3.0 file to view it and check its geometry. See Open and check CityGML and CityJSON.