typed-geojson
Strongly-typed GeoJSON for Rust.
Feature<G, P> / FeatureCollection<G, P>: generic over Geometry and
Properties, layered over the georust geojson
crate. With the specta feature it exports to TypeScript that is mutually
assignable with @types/geojson.
use ;
use ;
let raw = r#"{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [-96.8, 32.8] },
"properties": { "id": 7, "name": "DFW", "temp_c": 31.5 }
}"#;
let feature: = from_str.unwrap;
assert_eq!;
What you get
Feature<G, P>/FeatureCollection<G, P>: native parameter order;Gdefaults to the [Geometry] union,Pto an untyped JSON object.- Typed geometry (
Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon,GeometryCollection, and theGeometryunion), each matching its native@types/geojsonshape. - serde that round-trips to/from spec GeoJSON: validates
"type", tolerates foreign members, keepsid/bbox, omits an absentbbox. TryFrombridges to/from the untypedgeojsoncrate.
Nullability lives in G
Geometry is required but may be null (RFC 7946); like native, that nullability
is a choice of G:
type Located = ; // geometry: Geometry (non-null)
type Unlocated = ; // geometry: Geometry | null
type PointFeat = ; // geometry: Point
TypeScript (specta feature)
Feature<Point, Props> exports to a TS Feature<Point, Props> assignable to
and from GeoJSON.Feature<GeoJSON.Point, Props>: zero tsc errors, both ways.
let types = specta_types;
let ts = default
.export?;
Two details make it line up: bbox is a tuple union ([n,n,n,n] | [n,…×6]),
not number[]; each geometry's "type" is a string literal. ts/ holds the
assignability harness, gated in CI by tsc --noEmit.
Benchmarks
cargo bench, a 1k-point FeatureCollection with typed properties, vs the
untyped geojson baseline:
| variant | deserialize | serialize |
|---|---|---|
untyped geojson |
~538 µs | ~176 µs |
| typed properties | ~341 µs | ~158 µs |
typed properties + our Geometry |
~396 µs | ~176 µs |
Typed is ~30% faster to deserialize (typed properties skip the untyped JSON
map); the untagged Geometry union adds ~16% on reads. Serialize is on par.
License
Licensed under either Apache-2.0 or MIT at your option. Contributions are dual-licensed as above unless stated otherwise.