These are three minimal examples demonstrating GeoJSON parsing using Rust. In order to run them, you'll need at least Stable Rust 1.34. In most cases, the easiest way to do this is using Rustup.
If you aren't familiar with it, it may be helpful to familiarise yourself with the GeoJSON spec, as this should make it obvious why e.g. Feature geometries in rust-geojson are Option.
The example GeoJSON used is deliberately baroque: GeometryCollection isn't in wide use, and the use of nested GeometryCollections is discouraged by the spec, being all but unknown "in the wild". Nevertheless, if we need to e.g. extract all Polygon objects in an arbitrary GeoJSON file, we have to be able to process them – this turns out to be relatively painless using a recursive function.
The example code could be more minimal, but this is an ideal use case for Rayon in order to parallelise the processing, so iterators have been substituted for for { … } loops to faciliate its use, leading to the requirement for Rust 1.21 or later. If you'd prefer to use for loops and avoid iterators, the plain branch is available.
Three different approaches to parsing GeoJSON are shown:
borrowed.rsshows parsing using only borrowed data, and does not consume the GeoJSON, clone any part of it, or allocate – you're free to usegeojsonagain as soon asprocess_geojsonreturns. Run it using cargo:cargo run --bin borrowedowned.rsshows parsing and conversion toGeotypes, which necessarily consumes the GeoJSON, asGeo's primitives currently require owned data. To faciliate conversions of this kind,rust-geojsonprovides theconversion::try_intotrait for this on itsValuestructs. This approach is the most flexible, especially if you need to add or remove data, as opposed to modifying it. Run it using cargo:cargo run --bin ownedborrowed_modify.rs(Run it using cargo:cargo run --bin borrowed_modify) shows parsing and modification of geometries using only mutably borrowed data. The core idea can be seen incalculate_hull(): ordinarily,take()could be used to remove theTfrom anOption<T>– in this case aGeometry– convert itsvalueto aGeotype, and modify it before replacing it. However, this approach will only work for theFeaturetype; input which contains top-levelGeometryand/orGeometryCollectiontypes can't be modified in this way, due to the lack ofOption. However, a more general approach involvingstd::mem::replace, is possible:- We match against
&mut Geometry(which allGeoJsonenum variants are guaranteed to have) on itsvalue, wrapping that in anOption - This is passed to the conversion function
- In the conversion function, a non-allocating
Geoplaceholder geometry is constructed, converted into aValue, and swapped for theValuewe wish to modify, usingreplace. The original geometry can then be modified or freely used, before being swapped back into the borrowedGeometry.value, before the function returns.
- We match against
The polylabel_cmd crate contains more advanced parsing and conversion code which has the same structure as these examples.