Skip to content

Commit

Permalink
Parse inner GeoJson members directly from str
Browse files Browse the repository at this point in the history
Before:

    let gj = geojson::GeoJson::from_str(#r"{"type": "Geometry", "coordinates": [1, 2]}"#);
    let geom = Geometry::try_from(gj);

After:

    let geom = geojson::Geometry::from_str(#r"{"type": "Geometry", "coordinates": [1, 2]}"#);
  • Loading branch information
michaelkirk committed May 27, 2022
1 parent 70a8e20 commit 0db2aca
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* <https://github.com/georust/geojson/pull/182>
* Overhauled front page documentation.
* <https://github.com/georust/geojson/pull/183>
* Parse `Geometry`/`Feature`/`FeatureCollection` directly from str rather than
via `GeoJson` when you know what you're expecting.

## 0.22.3

Expand Down
48 changes: 48 additions & 0 deletions src/feature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

use std::convert::TryFrom;
use std::str::FromStr;

use crate::errors::Error;
use crate::json::{json, Deserialize, Deserializer, JsonObject, JsonValue, Serialize, Serializer};
Expand Down Expand Up @@ -42,6 +43,14 @@ impl From<Value> for Feature {
}
}

impl FromStr for Feature {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::try_from(crate::GeoJson::from_str(s)?)
}
}

impl<'a> From<&'a Feature> for JsonObject {
fn from(feature: &'a Feature) -> JsonObject {
let mut map = JsonObject::new();
Expand Down Expand Up @@ -211,8 +220,11 @@ impl Serialize for Id {

#[cfg(test)]
mod tests {
use crate::json::json;
use crate::{feature, Error, Feature, GeoJson, Geometry, Value};

use std::str::FromStr;

fn feature_json_str() -> &'static str {
"{\"geometry\":{\"coordinates\":[1.1,2.1],\"type\":\"Point\"},\"properties\":{},\"type\":\
\"Feature\"}"
Expand Down Expand Up @@ -460,4 +472,40 @@ mod tests {
assert_eq!(feature.contains_property("foo"), false);
assert_eq!(feature.properties_iter().collect::<Vec<_>>(), vec![]);
}

#[test]
fn test_from_str_ok() {
let feature_json = json!({
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
})
.to_string();

let feature = Feature::from_str(&feature_json).unwrap();
assert_eq!("Dinagat Islands", feature.property("name").unwrap());
}

#[test]
fn test_from_str_with_unexpected_type() {
let geometry_json = json!({
"type": "Point",
"coordinates": [125.6, 10.1]
})
.to_string();

let actual_failure = Feature::from_str(&geometry_json).unwrap_err();
match actual_failure {
Error::ExpectedType { actual, expected } => {
assert_eq!(actual, "Geometry");
assert_eq!(expected, "Feature");
}
e => panic!("unexpected error: {}", e),
};
}
}
62 changes: 61 additions & 1 deletion src/feature_collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

use std::convert::TryFrom;
use std::iter::FromIterator;
use std::str::FromStr;

use crate::errors::Error;
use crate::json::{json, Deserialize, Deserializer, JsonObject, JsonValue, Serialize, Serializer};
Expand Down Expand Up @@ -132,6 +133,14 @@ impl TryFrom<JsonValue> for FeatureCollection {
}
}

impl FromStr for FeatureCollection {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::try_from(crate::GeoJson::from_str(s)?)
}
}

impl Serialize for FeatureCollection {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down Expand Up @@ -222,7 +231,10 @@ impl FromIterator<Feature> for FeatureCollection {

#[cfg(test)]
mod tests {
use crate::{Feature, FeatureCollection, Value};
use crate::json::json;
use crate::{Error, Feature, FeatureCollection, Value};

use std::str::FromStr;

#[test]
fn test_fc_from_iterator() {
Expand All @@ -244,4 +256,52 @@ mod tests {
assert_eq!(fc.features.len(), 2);
assert_eq!(fc.bbox, Some(vec![-1., -1., -1., 11., 11., 11.]));
}

#[test]
fn test_from_str_ok() {
let fc_json = json!({ "type": "FeatureCollection", "features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
},
]})
.to_string();

let feature_collection = FeatureCollection::from_str(&fc_json).unwrap();
assert_eq!(2, feature_collection.features.len());
}

#[test]
fn test_from_str_with_unexpected_type() {
let geometry_json = json!({
"type": "Point",
"coordinates": [125.6, 10.1]
})
.to_string();

let actual_failure = FeatureCollection::from_str(&geometry_json).unwrap_err();
match actual_failure {
Error::ExpectedType { actual, expected } => {
assert_eq!(actual, "Geometry");
assert_eq!(expected, "FeatureCollection");
}
e => panic!("unexpected error: {}", e),
};
}
}
50 changes: 48 additions & 2 deletions src/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::str::FromStr;
use std::{convert::TryFrom, fmt};

use crate::errors::Error;
Expand Down Expand Up @@ -300,6 +301,14 @@ impl TryFrom<JsonValue> for Geometry {
}
}

impl FromStr for Geometry {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::try_from(crate::GeoJson::from_str(s)?)
}
}

impl Serialize for Geometry {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down Expand Up @@ -333,9 +342,10 @@ where

#[cfg(test)]
mod tests {
use std::str::FromStr;

use crate::json::JsonObject;
use crate::{GeoJson, Geometry, Value};
use crate::json::{json, JsonObject};
use crate::{Error, GeoJson, Geometry, Value};

fn encode(geometry: &Geometry) -> String {
serde_json::to_string(&geometry).unwrap()
Expand Down Expand Up @@ -466,4 +476,40 @@ mod tests {
};
assert_eq!(decoded_geometry, geometry_collection);
}

#[test]
fn test_from_str_ok() {
let geometry_json = json!({
"type": "Point",
"coordinates": [125.6f64, 10.1]
})
.to_string();

let geometry = Geometry::from_str(&geometry_json).unwrap();
assert!(matches!(geometry.value, Value::Point(_)));
}

#[test]
fn test_from_str_with_unexpected_type() {
let feature_json = json!({
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
})
.to_string();

let actual_failure = Geometry::from_str(&feature_json).unwrap_err();
match actual_failure {
Error::ExpectedType { actual, expected } => {
assert_eq!(actual, "Feature");
assert_eq!(expected, "Geometry");
}
e => panic!("unexpected error: {}", e),
};
}
}

0 comments on commit 0db2aca

Please sign in to comment.