F · Extensions
CityGML ADEs and CityJSON Extensions, typed where possible, every added name carrying its extension's namespace.
How CityParquet carries extensions to the CityGML conceptual model — a CityGML ADE, or the equivalent CityJSON Extension: each extension is identified by a short namespace, every name it adds carries that namespace as a prefix, and extension data is promoted to typed columns where Parquet allows it.
Extensions: a namespace prefix on every added name
decidedDecision. Each extension a package uses has a namespace (^[a-z][a-z0-9]*$, unique within the package), derived from the CityJSON extensions member key or the ADE’s XML-namespace prefix ("Energy" → energy). Every name the extension adds carries the prefix <namespace>_; core names and core module files never do. With the Energy ADE 3.0 as the example, see the specification:
- Extended feature types → grouped by module like core types: a class whose extension declares its own module gets a file named after that module with the namespace prefix (the Building Physics module →
energy_building_physics.parquet), while a class specialising an existing class joins that class’s module file.object_typecarries the prefix too (+ThermalZone→energy_ThermalZone). - Extended semantic surfaces → the prefixed type, inside the
geometry_properties_lod*surfacesvalue (+PartyWallSurface→energy_PartyWallSurface). - Extended attributes → typed columns with the prefixed name (
+heatCapacity→energy_heatCapacity).
The extensions key of the footer metadata maps each namespace to the extension’s name, schema url (a JSON Schema for a CityJSON Extension, an XSD for a CityGML ADE), optional version and, for an ADE, its xmlns. The schema is referenced, not embedded. A core name that starts with a declared namespace followed by _ is a hard error.
Alternatives considered.
- Keeping all extension data in the
otherJSON escape hatch, rather than promoting extension attributes to first-class typed columns. - Keeping CityJSON’s
+in column, type and file names (+heatCapacity,+building_physics.parquet). - A fixed
ex_prefix in place of the+for attribute columns (ex_heatCapacity), with semantic surface types keeping their+and file names dropping it. Considered and rejected: it marks a name as some extension’s without saying which, so two extensions’ names can collide, an extension module can collide with a core module of the same name (the Energy ADE declares a module namedBuilding), and a genuine core attribute beginningex_cannot be told apart. - Embedding the extension’s schema in the footer, with a source-name ↔ class ↔ module mapping, rather than referencing the schema by URL.
Why this. Extension attributes benefit from the same typed-column advantages as core attributes, so they are promoted — but a leading + cannot be used unquoted in SQL and causes problems in database table and column names and in generated bindings. A namespace solves that and also keeps the names of different extensions apart, as XML namespaces do for CityGML ADEs, which a bare + or a fixed ex_ cannot. Applying one rule to attributes, surface types, classes and module files means a reader identifies every extension name the same way, and export restores CityJSON’s + by stripping a declared prefix, so no separate mapping is needed: a class’s module is the file its row sits in. Referencing the schema keeps the footer small and leaves the schema authoritative where it is published.
Trade-off. Extended names become longer, and a reader must look up a prefix in city.extensions to identify the extension behind it. Core names beginning with a declared namespace and _ must be rejected. Attributing + names when one CityJSON source declares several extensions needs those extensions’ schema documents. The full object-class metadata of an ADE is not represented.
Status. Decided. The implementation status records what each implementation supports; fetching schema documents named only by URL, reading a CityJSON Extension’s schema document, and full ADE object-class metadata are open — see the Open questions.