From c4b32cdc6c3fc1d3f2dccffeb3dc61fde5ef7840 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 10 May 2016 16:08:56 -0400 Subject: [PATCH] Permit `geometry` field on `feature` objects to be `null`. Fixes https://github.com/georust/rust-geojson/issues/42. --- CHANGES.md | 5 +++++ Cargo.toml | 2 +- README.md | 2 +- src/feature.rs | 27 +++++++++++++++++++++++---- src/lib.rs | 9 ++++++++- src/util.rs | 13 ++++++++++--- 6 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 CHANGES.md diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 00000000..da001e7d --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,5 @@ +# Changes + +## 0.3.0 + +* [Permit `geometry` field on `feature` objects to be `null`](https://github.com/georust/rust-geojson/issues/42) diff --git a/Cargo.toml b/Cargo.toml index f83ccf1e..2c5ddd8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "geojson" description = "Library for serializing the GeoJSON vector GIS file format" -version = "0.2.1" +version = "0.3.0" authors = ["Corey Farwell ", "Blake Grotewold "] license = "MIT/Apache-2.0" diff --git a/README.md b/README.md index 28bdcc50..a652ea3e 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ properties.insert( let geojson = GeoJson::Feature(Feature { crs: None, bbox: None, - geometry: geometry, + geometry: Some(geometry), id: None, properties: Some(properties), }); diff --git a/src/feature.rs b/src/feature.rs index 020a855e..c051b24c 100644 --- a/src/feature.rs +++ b/src/feature.rs @@ -31,7 +31,7 @@ use ::{Bbox, Crs, Error, FromObject, Geometry, util}; pub struct Feature { pub bbox: Option, pub crs: Option, - pub geometry: Geometry, + pub geometry: Option, pub id: Option, pub properties: Option, } @@ -105,7 +105,7 @@ impl Deserialize for Feature { #[cfg(test)] mod tests { - use ::{Feature, Geometry, Value, GeoJson}; + use ::{Error, Feature, Geometry, Value, GeoJson}; fn feature_json_str() -> &'static str { "{\"geometry\":{\"coordinates\":[1.1,2.1],\"type\":\"Point\"},\"properties\":{},\"type\":\"Feature\"}" @@ -124,11 +124,11 @@ mod tests { fn feature() -> Feature { ::Feature { - geometry: Geometry { + geometry: Some(Geometry { value: Value::Point(vec![1.1, 2.1]), crs: None, bbox: None, - }, + }), properties: properties(), crs: None, bbox: None, @@ -173,4 +173,23 @@ mod tests { }; assert_eq!(decoded_feature, feature); } + + #[test] + fn feature_json_null_geometry() { + let geojson_str = r#"{ + "geometry": null, + "properties":{}, + "type":"Feature" + }"#; + assert!(geojson_str.parse::().is_ok()); + } + + #[test] + fn feature_json_invalid_geometry() { + let geojson_str = r#"{"geometry":3.14,"properties":{},"type":"Feature"}"#; + match geojson_str.parse::().unwrap_err() { + Error::FeatureInvalidGeometryValue => (), + _ => unreachable!(), + } + } } diff --git a/src/lib.rs b/src/lib.rs index 5ecb7ebe..363a0def 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -108,7 +108,7 @@ //! let geojson = GeoJson::Feature(Feature { //! crs: None, //! bbox: None, -//! geometry: geometry, +//! geometry: Some(geometry), //! id: None, //! properties: Some(properties), //! }); @@ -171,6 +171,7 @@ pub enum Error { GeometryUnknownType, MalformedJson, PropertiesExpectedObjectOrNull, + FeatureInvalidGeometryValue, // FIXME: make these types more specific ExpectedStringValue, @@ -209,6 +210,10 @@ impl std::fmt::Display for Error { // FIXME: inform what type we actually found write!(f, "Encountered neither object type nor null type for \ 'properties' object."), + Error::FeatureInvalidGeometryValue => + // FIXME: inform what type we actually found + write!(f, "Encountered neither object type nor null type for \ + 'geometry' field on 'feature' object."), Error::ExpectedStringValue => write!(f, "Expected a string value."), Error::ExpectedProperty => @@ -236,6 +241,8 @@ impl std::error::Error for Error { Error::MalformedJson => "malformed JSON", Error::PropertiesExpectedObjectOrNull => "neither object type nor null type for properties' object.", + Error::FeatureInvalidGeometryValue => + "neither object type nor null type for 'geometry' field on 'feature' object.", Error::ExpectedStringValue => "expected a string value", Error::ExpectedProperty => "expected a GeoJSON 'property'", Error::ExpectedF64Value => "expected a floating-point value", diff --git a/src/util.rs b/src/util.rs index 4eb6762c..4727c7d6 100644 --- a/src/util.rs +++ b/src/util.rs @@ -120,9 +120,16 @@ pub fn get_id(object: &JsonObject) -> Result, Error> { } /// Used by Feature -pub fn get_geometry(object: &JsonObject) -> Result { - let geometry = expect_object!(expect_property!(object, "geometry", "Missing 'geometry' field")); - return Geometry::from_object(geometry); +pub fn get_geometry(object: &JsonObject) -> Result, Error> { + let geometry = expect_property!(object, "geometry", "Missing 'geometry' field"); + match *geometry { + JsonValue::Object(ref x) => { + let geometry_object = try!(Geometry::from_object(x)); + Ok(Some(geometry_object)) + }, + JsonValue::Null => Ok(None), + _ => Err(Error::FeatureInvalidGeometryValue), + } } /// Used by FeatureCollection