Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
cityjson-json
cityjson-json is a CityJSON 2.0 serde adapter around the cityjson crate. It provides efficient serialization and deserialization of CityJSON documents with both owned and borrowed string storage options.
Benchmarks
Representative read benchmarks against serde_json::Value. Refresh this table
from the shared benchmark suite with just bench.
| Case | Owned | Borrowed | serde_json::Value |
Owned vs Value | Borrowed vs Value |
|---|---|---|---|---|---|
io_basisvoorziening_3d_cityjson |
282.4 MiB/s | 313.5 MiB/s | 251.1 MiB/s | 1.13x | 1.25x |
io_3dbag_cityjson_cluster_4x |
186.8 MiB/s | 196.2 MiB/s | 290.8 MiB/s | 0.64x | 0.67x |
io_3dbag_cityjson |
192.9 MiB/s | 205.8 MiB/s | 308.3 MiB/s | 0.63x | 0.67x |
Full benchmark tables and plots are written to benches/results/benchmark_summary.md.
Use just bench-local /path/to/file-or-directory for ad hoc local inputs without
rewriting this README snapshot.
Installation
cargo add cityjson-json
Getting Started
Imports
use ;
use ;
Owned Deserialization
For simple use cases, deserialize into an owned model:
use from_str_owned;
let json_str = r#"{
"type": "CityJSON",
"version": "2.0",
"transform": {"scale": [1.0, 1.0, 1.0], "translate": [0.0, 0.0, 0.0]},
"CityObjects": {},
"vertices": []
}"#;
let model = from_str_owned?;
# Ok::
Borrowed Deserialization
For performance-critical applications, use borrowed deserialization to avoid allocations:
use from_str_borrowed;
let json_str = r#"{"type":"CityJSON","version":"2.0","transform":{"scale":[1.0,1.0,1.0],"translate":[0.0,0.0,0.0]},"CityObjects":{},"vertices":[]}"#;
let model = from_str_borrowed?;
// model holds references to json_str
# Ok::
Serialization
Serialize models back to JSON using the as_json builder:
use as_json;
let json_output = as_json.to_string?;
The same builder works for other output targets:
use as_json;
let bytes = as_json.to_vec?;
as_json.validate.to_writer?;
CityJSONSeq
Read a newline-delimited CityJSONSeq stream. The first line must be a CityJSON header; each subsequent line is a self-contained CityJSONFeature:
use BufReader;
use read_cityjsonseq;
let seq = concat!;
let features = read_cityjsonseq?
.?;
// each element is an OwnedCityModel (CityJSONFeature) with the header transform merged in
# Ok::
Write a strict CityJSONSeq stream. Supply a CityJSON base root and one or more feature models; the builder quantizes vertices and computes the geographical extent:
use ;
let base_input = r#"{"type":"CityJSON","version":"2.0","transform":{"scale":[1.0,1.0,1.0],"translate":[0.0,0.0,0.0]},"CityObjects":{},"vertices":[]}"#;
let base_root = from_str_owned?;
let feature = from_feature_str_with_base?;
let mut output: = Vecnew;
let report = write_cityjsonseq
.auto_transform
.write?;
// report.feature_count == 1, report.geographical_extent covers all feature vertices
# Ok::
Documentation
todo: link to docs.rs
Library Layout
| Module | Contents |
|---|---|
v2_0 |
CityJSON 2.0 (de)serialization entry points, feature-stream helpers, and SerializableCityModel |
errors |
Error and Result types surfaced by the adapter |
| (root) | Convenience re-exports: from_str_*, as_json, write_cityjsonseq, model types |
Core types re-exported from cityjson:
OwnedCityModel: ACityJSONmodel with ownedStringstorage. Self-contained and doesn't depend on external lifetimes.BorrowedCityModel: ACityJSONmodel with borrowed string references. More memory efficient but requires careful lifetime management.
Design
The adapter is optimized around a small number of core decisions:
- deserialization is split into root preparation and streamed model construction
CityObjectsand geometry boundaries avoid large intermediate JSON structures- attributes deserialize directly into backend value types
- serialization streams from the model with a shared write context instead of building a DOM first
- both owned and borrowed string storage are supported through the same parsing pipeline
The full design description lives in docs/design.md.
API Stability
This crate follows semantic versioning (MAJOR.MINOR.PATCH):
MAJOR: incompatible API changesMINOR: backwards-compatible feature additionsPATCH: backwards-compatible fixes
Minimum Rust Version
The minimum supported rustc version is 1.93.0.
Development
Development setup, test configuration, and benchmark workflow are documented in docs/development.md.
Contributing
Contributions are welcome in all forms. Please open an issue to discuss any potential changes before working on a patch. You can submit LLM-generated PRs for bug fixes and documentation improvements. Regardless of handwritten or LLM-generated code, the PR should follow these guidelines:
- relatively small, focused changes, otherwise I won't be able to review it,
- follow the existing style and conventions,
- include unit tests and documentation for new features and bug fixes,
- the patched code should pass:
just ci
- if you remove or merge tests or examples or benchmarks, please explain why and update the documentation accordingly.
License
Licensed under either:
- Apache License, Version 2.0 (
LICENSE-APACHE) - MIT license (
LICENSE-MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in cityjson-json by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without additional terms or conditions.
Use of AI in this project
This crate was originally developed without the use of AI.
Since then, it underwent multiple significant refactors and various LLM models (Claude, ChatGPT) were used for experimenting with alternative designs, in particular for the (de)serialization strategies and borrowed-parsing paths.
LLM generated code is also used for improving the test coverage and documentation and mechanical improvements.
Code correctness and performance are verified by carefully curated test cases and benchmarks that cover the CityJSON 2.0 specification.
Roadmap
There are no major features planned for the near future, beyond bug fixes, test coverage, performance optimization, and documentation improvements.