geojson
repository·main·Indexed 43 days ago
https://github.com/georust/geojsonA Rust crate for reading and writing GeoJSON (RFC 7946) vector geographic data. It provides tools for high-level manipulation of GeoJSON objects such as Features, Geometries, and FeatureCollections, with support for serialization and deserialization via serde. Version 1.0.0 requires a minimum Rust version of 1.34.
What's inside geojson
- This library requires a minimum Rust version of 1.34 (released April 11 2019).
Use the GeoJson enum to handle any valid GeoJSON object
mainThe
GeoJsonenum is the primary entry point for working with GeoJSON in this crate. It acts as a container that can represent any valid GeoJSON object: aGeometry, aFeature, or aFeatureCollection. This is particularly useful when you are parsing data and do not know the specific type of GeoJSON object beforehand.Use
GeoJson::from_strorGeoJson::from_readerto parse JSON strings or streams into this enum, then use pattern matching to access the underlying data.use geojson::{GeoJson, Feature, FeatureCollection, Geometry}; // When you're not sure what you're getting, use `GeoJson`. let geojson_str = r#"{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": null }"#; let geojson: GeoJson = geojson_str.parse().unwrap(); match geojson { GeoJson::Geometry(geometry) => println!("geometry: {:?}", geometry), GeoJson::Feature(feature) => println!("feature: {:?}", feature), GeoJson::FeatureCollection(feature_collection) => { println!("feature_collection: {:?}", feature_collection) } }Understand GeometryValue and Geometry
mainThe library distinguishes between
GeometryValueandGeometry:GeometryValue: An enum representing the core GeoJSON geometry type and its specific coordinate structure (e.g.,Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon,GeometryCollection). It is the payload of a geometry.Geometry: A wrapper struct that follows the GeoJSON specification for a Geometry Object. It contains:value: TheGeometryValue(the type and coordinates).bbox: An optional bounding box (Option<Bbox>).foreign_members: An optional map of extra fields (Option<JsonObject>) allowed by the GeoJSON spec.
When creating geometries, it is recommended to use the
Geometry::new_*constructors which wrap aGeometryValueinto aGeometrystruct.How GeoJSON objects are structured
mainThe crate is structured around the GeoJSON spec (RFC 7946). A GeoJSON document is represented by the
GeoJsonenum, which can contain one of three top-level objects:Geometry: Represents points, lines, and surfaces in coordinate space.Feature: Contains aGeometryand associated data (properties).FeatureCollection: A list ofFeatures.
Because
FeatureandFeatureCollectionare more flexible, bareGeometrydocuments are less common. Conversions fromGeometryorGeometryValuetoFeatureobjects are provided via theFromtrait.use geojson::{GeoJson, Feature, FeatureCollection, Geometry};Handle Foreign Members in GeoJSON
mainGeoJSON allows for 'foreign members'—extra JSON fields not defined in the spec. This crate captures them in the
foreign_membersfield onGeometry,Feature, andFeatureCollectionstructs.Limitation: Foreign member keys must not collide with reserved GeoJSON fields (
coordinates,geometries,id,geometry,properties,features), or they will be consumed by the reserved field parser instead.use geojson::{GeoJson, Feature}; let geojson_str = r#"{ "type": "Feature", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": null, "title": "my point" }"#; let feature = geojson_str.parse::<GeoJson>().unwrap(); if let GeoJson::Feature(feature) = feature { let foreign_members = feature.foreign_members.unwrap(); assert_eq!(foreign_members["title"], "my point"); }Install the geojson crate
mainTo use this crate in your Rust project, add it to your
Cargo.tomlusingcargo add:cargo add geojsonUse your own types with serde
mainYou can deserialize GeoJSON directly into your own custom structs using
serde. To do this correctly:- Your struct must have a
geometryfield. - If the field is a
geo-typesgeometry, use thegeojson::ser::serialize_geometryandgeojson::de::deserialize_geometryhelpers. - Otherwise, the field must be a
crate::Geometry.
Note: Using this method means any fields other than
geometryandproperties(likeforeign_members) will be lost during deserialization.#[derive(Serialize, Deserialize)] struct MyStruct { #[serde(serialize_with = "geojson::ser::serialize_geometry", deserialize_with = "geojson::de::deserialize_geometry")] geometry: geo_types::Point<f64>, name: String, count: u64, }- Your struct must have a
Convert between geojson and geo-types
mainIf the
geo-typesfeature is enabled, you can convert betweengeojsontypes andgeo-typesgeometries.Convert
geo-typestogeojson(Lossless)Use the
Fromtrait to convertgeo-typesgeometries intogeojson::Geometryorgeojson::GeometryValue.Convert
geojsontogeo-types(Fallible)Use the
TryFromtrait to convertGeoJson,GeometryValue,Feature,FeatureCollection, orGeometryintogeo_types::Geometry<f64>. This is a fallible operation.Caveats:
- Round-tripping through
geo-typesmight not produce identical output (e.g., outerPolygonrings are automatically closed). geojsonmay re-orientPolygonrings during serialization to ensure valid geometries.
// Convert geojson to geo_types::Geometry<f64> #[cfg(feature = "geo-types")] use geo_types::Geometry; use geojson::GeoJson; use std::convert::TryFrom; use std::str::FromStr; let geojson_str = r#"{ "type": "Feature", "properties": {}, "geometry": { "type": "Point", "coordinates": [1.0, 2.0] } }"#; let geojson = GeoJson::from_str(geojson_str).unwrap(); let geom = Geometry::<f64>::try_from(geojson).unwrap();- Round-tripping through
Parse GeoJSON strings into GeoJson objects
mainYou can parse a GeoJSON string into a
GeoJsonenum using the.parse::<GeoJson>()method. This allows you to convert raw string data into structured Rust types representing GeoJSON features, geometries, or collections.use geojson::GeoJson; let geojson_str = r"# { "type": "Feature", "properties": { "name": "Firestone Grill" }, "geometry": { "type": "Point", "coordinates": [-120.66029,35.2812] } } "#; let geojson = geojson_str.parse::<GeoJson>().unwrap();Serialize GeoJSON objects to strings
mainTo write GeoJSON, construct the appropriate types such as
Geometry,JsonObject, andFeature, then wrap them in theGeoJsonenum. You can then use the.to_string()method to serialize the object into a GeoJSON-formatted string.use geojson::{Feature, GeoJson, Geometry, JsonObject, JsonValue}; let geometry = Geometry::new_point([-120.66029, 35.2812]); let mut properties = JsonObject::new(); properties.insert( String::from("name"), JsonValue::from("Firestone Grill"), ); let geojson = GeoJson::Feature(Feature { bbox: None, geometry: Some(geometry), id: None, properties: Some(properties), foreign_members: None, }); let geojson_string = geojson.to_string();Read GeoJSON from a string
mainYou can deserialize a GeoJSON string into a
Feature(or other GeoJSON types) by using thestr::parsemethod. This is powered byserdeintegration.use geojson::{Feature, GeoJson, Geometry, GeometryValue}; use std::convert::TryFrom; let geojson_str = r"# { "type": "Feature", "properties": { "food": "donuts" }, "geometry": { "type": "Point", "coordinates": [ -118.2836, 34.0956 ] } } "#; let feature: Feature = geojson_str.parse().unwrap(); // read property data assert_eq!("donuts", feature.property("food").unwrap()); // read geometry data let geometry: Geometry = feature.geometry.unwrap(); if let GeometryValue::Point { coordinates } = geometry.value { assert_eq!(coordinates.as_slice(), &[-118.2836, 34.0956]); }Write GeoJSON to a string
mainYou can serialize GeoJSON objects to a string by calling
.to_string(). ForFeatureobjects, you can define properties usingJsonObjectandJsonValue(which are wrappers aroundserde_jsontypes).use geojson::{Feature, GeoJson, Geometry, JsonObject, JsonValue}; fn get_properties() -> JsonObject { let mut properties = JsonObject::new(); properties.insert( String::from("name"), JsonValue::from("Firestone Grill"), ); properties } fn main() { let geometry = Geometry::new_point([-120.66029, 35.2812]); let feature = Feature { bbox: None, geometry: Some(geometry), id: None, properties: Some(get_properties()), foreign_members: None, }; let geojson_string = feature.to_string(); }