use jsonfg::{CoordRefSys, Feature, FeatureCollection, Geometry, conformance};
use serde_json::{Value, json};
fn roundtrip_feature(v: Value) {
let feature: Feature = serde_json::from_value(v.clone()).expect("deserialize Feature");
let back = serde_json::to_value(&feature).expect("serialize Feature");
assert_eq!(v, back, "feature did not round-trip");
}
fn roundtrip_collection(v: Value) {
let fc: FeatureCollection =
serde_json::from_value(v.clone()).expect("deserialize FeatureCollection");
let back = serde_json::to_value(&fc).expect("serialize FeatureCollection");
assert_eq!(v, back, "feature collection did not round-trip");
}
#[test]
fn wgs84_point_feature() {
roundtrip_feature(json!({
"type": "Feature",
"id": 1,
"geometry": { "type": "Point", "coordinates": [5.0, 52.0] },
"properties": { "name": "example" }
}));
}
#[test]
fn prism_feature() {
let v = json!({
"type": "Feature",
"id": "prism-1",
"conformsTo": [conformance::CORE, conformance::PRISMS],
"featureType": "example",
"time": { "interval": ["2022-07-12T16:55:18Z", ".."] },
"coordRefSys": "http://www.opengis.net/def/crs/EPSG/0/3857",
"place": {
"type": "Prism",
"base": {
"type": "LineString",
"coordinates": [[10.0, 20.0], [13.0, 23.0]]
},
"lower": 2.02,
"upper": 3.22
},
"geometry": null,
"properties": null
});
roundtrip_feature(v.clone());
let f: Feature = serde_json::from_value(v).unwrap();
assert!(f.geometry.is_none());
assert!(matches!(f.place, Some(Geometry::Prism { upper, .. }) if upper == 3.22));
assert!(!f.coord_ref_sys.as_ref().unwrap().is_wgs84());
}
#[test]
fn curve_polygon_feature() {
roundtrip_feature(json!({
"type": "Feature",
"id": "curve-1",
"conformsTo": [conformance::CORE, conformance::CIRCULAR_ARCS],
"featureType": "example",
"coordRefSys": "http://www.opengis.net/def/crs/EPSG/0/3857",
"place": {
"type": "CurvePolygon",
"geometries": [{
"type": "CompoundCurve",
"geometries": [
{ "type": "LineString", "coordinates": [[1.0, 1.0], [2.0, 1.0]] },
{ "type": "CircularString", "coordinates": [[2.0, 1.0], [2.5, 1.5], [2.0, 2.0]] },
{ "type": "LineString", "coordinates": [[2.0, 2.0], [1.0, 1.0]] }
]
}]
},
"geometry": null,
"properties": { "year": 1975 }
}));
}
#[test]
fn polyhedron_place() {
roundtrip_feature(json!({
"type": "Feature",
"conformsTo": [conformance::CORE, conformance::POLYHEDRA],
"coordRefSys": "http://www.opengis.net/def/crs/EPSG/0/3857",
"place": {
"type": "Polyhedron",
"coordinates": [[
[[[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0], [0.0, 0.0, 0.0]]],
[[[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0], [0.0, 0.0, 0.0]]]
]]
},
"geometry": null,
"properties": null
}));
}
#[test]
fn geometry_with_bbox_and_coordrefsys() {
let v = json!({
"type": "Polygon",
"coordRefSys": "http://www.opengis.net/def/crs/EPSG/0/3857",
"bbox": [0.0, 0.0, 10.0, 10.0],
"coordinates": [[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 0.0]]]
});
let g: Geometry = serde_json::from_value(v.clone()).unwrap();
assert_eq!(g.meta().bbox.as_ref().unwrap(), &vec![0.0, 0.0, 10.0, 10.0]);
assert_eq!(serde_json::to_value(&g).unwrap(), v);
}
#[test]
fn feature_collection_with_ogc_api_members() {
roundtrip_collection(json!({
"type": "FeatureCollection",
"conformsTo": [conformance::CORE],
"coordRefSys": "http://www.opengis.net/def/crs/EPSG/0/3857",
"features": [
{
"type": "Feature",
"id": 1,
"place": { "type": "Point", "coordinates": [100.0, 200.0] },
"geometry": null,
"properties": null
}
],
"links": [
{ "href": "https://example.com/items?f=jsonfg", "rel": "self",
"type": "application/vnd.ogc.fg+json" }
],
"timeStamp": "2026-01-01T12:00:00Z",
"numberMatched": 1,
"numberReturned": 1
}));
}
#[test]
fn empty_collection_serializes_features_array() {
let fc = FeatureCollection::new();
let v = serde_json::to_value(&fc).unwrap();
assert_eq!(v["type"], "FeatureCollection");
assert_eq!(v["features"], json!([]));
}
#[test]
fn feature_always_emits_geometry_and_properties() {
let v = serde_json::to_value(Feature::new()).unwrap();
assert!(v.get("geometry").is_some() && v["geometry"].is_null());
assert!(v.get("properties").is_some() && v["properties"].is_null());
assert!(v.get("place").is_none());
assert!(v.get("time").is_none());
}
#[test]
fn coord_ref_sys_helpers() {
assert_eq!(
serde_json::to_value(CoordRefSys::from_epsg(3857)).unwrap(),
json!("http://www.opengis.net/def/crs/EPSG/0/3857")
);
assert!(CoordRefSys::crs84().is_wgs84());
assert!(!CoordRefSys::from_epsg(3857).is_wgs84());
}
#[test]
fn coord_ref_sys_reference_object() {
let v = json!({ "type": "Reference", "href": "http://www.opengis.net/def/crs/EPSG/0/4979", "epoch": 2017.23 });
let crs: CoordRefSys = serde_json::from_value(v.clone()).unwrap();
assert_eq!(serde_json::to_value(&crs).unwrap(), v);
}
#[cfg(feature = "geojson")]
#[test]
fn geojson_interop() {
let gj: geojson::Geometry = serde_json::from_value(json!({
"type": "Polygon",
"coordinates": [[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]]
}))
.unwrap();
let fg: Geometry = gj.clone().into();
assert!(matches!(fg, Geometry::Polygon { .. }));
let back: geojson::Geometry = fg.try_into().unwrap();
assert_eq!(back.value, gj.value);
let arc = Geometry::CircularString {
coordinates: vec![vec![0.0, 0.0], vec![1.0, 1.0], vec![2.0, 0.0]],
meta: Default::default(),
};
assert!(geojson::Geometry::try_from(arc).is_err());
}