diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d452d48d..2e78bf89 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,6 @@ jobs: - "-p stac -F reqwest" - "-p stac-api" - "-p stac -p stac-api -F geo" - - "-p stac -p stac-api -F schemars" - "-p stac-async" - "-p stac-cli --no-default-features" - "-p stac-validate" @@ -53,7 +52,7 @@ jobs: - name: Set up Rust cache uses: Swatinem/rust-cache@v2 - name: Test - run: cargo test --no-default-features -F reqwest -F geo -F schemars + run: cargo test --no-default-features -F reqwest -F geo test-macos: runs-on: macos-latest steps: @@ -61,7 +60,7 @@ jobs: - name: Set up Rust cache uses: Swatinem/rust-cache@v2 - name: Test - run: cargo test --no-default-features -F reqwest -F geo -F schemars + run: cargo test --no-default-features -F reqwest -F geo build: runs-on: ubuntu-latest steps: diff --git a/stac-api/CHANGELOG.md b/stac-api/CHANGELOG.md index 8c3d6939..d9c183b1 100644 --- a/stac-api/CHANGELOG.md +++ b/stac-api/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Removed + +- `schemars` feature ([#245](https://github.com/stac-utils/stac-rs/pull/245)) + ## [0.3.3] - 2024-04-07 ### Added diff --git a/stac-api/Cargo.toml b/stac-api/Cargo.toml index 6ca9f756..6703f10a 100644 --- a/stac-api/Cargo.toml +++ b/stac-api/Cargo.toml @@ -12,11 +12,10 @@ categories = ["science", "data-structures", "web-programming"] [features] geo = ["dep:geo", "stac/geo"] -schemars = ["dep:schemars", "stac/schemars"] [dependencies] geo = { version = "0.28", optional = true } -schemars = { version = "0.8", optional = true } +geojson = "0.24" serde = "1" serde_json = "1" serde_urlencoded = "0.7" diff --git a/stac-api/README.md b/stac-api/README.md index 7f1447fd..b946efa2 100644 --- a/stac-api/README.md +++ b/stac-api/README.md @@ -19,7 +19,7 @@ To use the library in your project: stac-api = "0.3" ``` -**stac-api** has two optional features. +**stac-api** has one optional feature. `geo` enables `Search::match`: ```toml @@ -27,14 +27,6 @@ stac-api = "0.3" stac-api = { version = "0.3", features = ["geo"] } ``` -`schemars`, can be used to generate [jsonschema](https://json-schema.org/) documents for the API structures. -This is useful for auto-generating OpenAPI documentation: - -```toml -[dependencies] -stac-api = { version = "0.3", features = ["schemars"] } -``` - ## Examples ```rust diff --git a/stac-api/src/collections.rs b/stac-api/src/collections.rs index f48bb7e7..96cddd58 100644 --- a/stac-api/src/collections.rs +++ b/stac-api/src/collections.rs @@ -4,7 +4,6 @@ use stac::{Collection, Link, Links}; /// Object containing an array of collections and an array of links. #[derive(Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Collections { /// The [Collection] objects in the [stac::Catalog]. pub collections: Vec, diff --git a/stac-api/src/conformance.rs b/stac-api/src/conformance.rs index 2f417fb5..1b68c85c 100644 --- a/stac-api/src/conformance.rs +++ b/stac-api/src/conformance.rs @@ -23,7 +23,6 @@ pub const ITEM_SEARCH_URI: &str = "https://api.stacspec.org/v1.0.0/item-search"; /// implementations - and not "just" a specific API / server, the server has to /// declare the conformance classes it implements and conforms to. #[derive(Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Conformance { /// The conformance classes it implements and conforms to. #[serde(rename = "conformsTo")] diff --git a/stac-api/src/error.rs b/stac-api/src/error.rs index 017bb488..fbaeb2ef 100644 --- a/stac-api/src/error.rs +++ b/stac-api/src/error.rs @@ -16,6 +16,10 @@ pub enum Error { #[error("cannot convert cql2-json to strings")] CannotConvertCql2JsonToString(Map), + /// [geojson::Error] + #[error(transparent)] + GeoJson(#[from] geojson::Error), + /// [std::num::ParseIntError] #[error(transparent)] ParseIntError(#[from] std::num::ParseIntError), diff --git a/stac-api/src/fields.rs b/stac-api/src/fields.rs index e91cc2c4..191461a2 100644 --- a/stac-api/src/fields.rs +++ b/stac-api/src/fields.rs @@ -14,7 +14,6 @@ use std::{ /// specification provides a mechanism for clients to request that servers to /// explicitly include or exclude certain fields. #[derive(Clone, Debug, Serialize, Deserialize, Default, PartialEq)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Fields { /// Fields to include. #[serde(skip_serializing_if = "Vec::is_empty")] diff --git a/stac-api/src/filter.rs b/stac-api/src/filter.rs index 04de30d0..306ed184 100644 --- a/stac-api/src/filter.rs +++ b/stac-api/src/filter.rs @@ -4,7 +4,6 @@ use serde_json::{Map, Value}; /// The language of the filter expression. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[serde(tag = "filter-lang", content = "filter")] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub enum Filter { /// `cql2-text` #[serde(rename = "cql2-text")] diff --git a/stac-api/src/item_collection.rs b/stac-api/src/item_collection.rs index 44263b77..e252fda6 100644 --- a/stac-api/src/item_collection.rs +++ b/stac-api/src/item_collection.rs @@ -12,7 +12,6 @@ const ITEM_COLLECTION_TYPE: &str = "FeatureCollection"; /// not be. Defined by the [itemcollection /// fragment](https://github.com/radiantearth/stac-api-spec/blob/main/fragments/itemcollection/README.md). #[derive(Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct ItemCollection { #[serde( deserialize_with = "deserialize_type", @@ -50,7 +49,6 @@ pub struct ItemCollection { /// /// Part of the [context extension](https://github.com/stac-api-extensions/context). #[derive(Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Context { /// The count of results returned by this response. Equal to the cardinality /// of features array. diff --git a/stac-api/src/items.rs b/stac-api/src/items.rs index 83170303..1743f8f1 100644 --- a/stac-api/src/items.rs +++ b/stac-api/src/items.rs @@ -8,7 +8,6 @@ use std::collections::HashMap; /// This is a lot like [Search](crate::Search), but without intersects, ids, and /// collections. #[derive(Clone, Default, Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Items { /// The maximum number of results to return (page size). #[serde(skip_serializing_if = "Option::is_none")] @@ -59,7 +58,6 @@ pub struct Items { /// This is a lot like [Search](crate::Search), but without intersects, ids, and /// collections. #[derive(Clone, Default, Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct GetItems { /// The maximum number of results to return (page size). #[serde(skip_serializing_if = "Option::is_none")] diff --git a/stac-api/src/root.rs b/stac-api/src/root.rs index 59598989..b092429b 100644 --- a/stac-api/src/root.rs +++ b/stac-api/src/root.rs @@ -24,7 +24,6 @@ use stac::Catalog; /// URI is listed then the service must implement all of the required /// capabilities. #[derive(Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Root { /// The [stac::Catalog]. #[serde(flatten)] diff --git a/stac-api/src/search.rs b/stac-api/src/search.rs index bc738e2e..b4d98c45 100644 --- a/stac-api/src/search.rs +++ b/stac-api/src/search.rs @@ -1,12 +1,12 @@ use crate::{Error, Fields, Filter, GetItems, Items, Result, Sortby}; +use geojson::Geometry; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; -use stac::{Geometry, Item}; +use stac::Item; use std::collections::HashMap; /// The core parameters for STAC search are defined by OAFeat, and STAC adds a few parameters for convenience. #[derive(Clone, Default, Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Search { /// The maximum number of results to return (page size). #[serde(skip_serializing_if = "Option::is_none")] @@ -68,7 +68,6 @@ pub struct Search { /// GET parameters for the item search endpoint. #[derive(Clone, Default, Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct GetSearch { /// The maximum number of results to return (page size). #[serde(skip_serializing_if = "Option::is_none")] @@ -158,9 +157,11 @@ impl Search { /// /// ``` /// use stac_api::Search; + /// use geojson::{Geometry, Value}; + /// /// let mut search = Search { bbox: Some(vec![-180.0, -90.0, 180.0, 80.0]), ..Default::default() }; /// search.validate().unwrap(); - /// search.intersects = Some(stac::Geometry::point(0., 0.)); + /// search.intersects = Some(Geometry::new(Value::Point(vec![0.0, 0.0]))); /// let _ = search.validate().unwrap_err(); /// ``` pub fn validate(&self) -> Result<()> { @@ -292,7 +293,7 @@ impl Search { /// let mut search = Search::new(); /// let mut item = Item::new("item-id"); /// assert!(search.intersects_matches(&item).unwrap()); - /// search.intersects = Some(stac::Geometry::point(-105.1, 41.1)); + /// search.intersects = Some(Geometry::new(Value::Point(vec![-105.1, 41.1]))); /// assert!(!search.intersects_matches(&item).unwrap()); /// item.set_geometry(Geometry::new(Value::Point(vec![-105.1, 41.1]))); /// assert!(search.intersects_matches(&item).unwrap()); diff --git a/stac-api/src/sort.rs b/stac-api/src/sort.rs index c825e3b8..252ef6c5 100644 --- a/stac-api/src/sort.rs +++ b/stac-api/src/sort.rs @@ -7,7 +7,6 @@ use std::{ /// Fields by which to sort results. #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Sortby { /// The field to sort by. pub field: String, @@ -17,7 +16,6 @@ pub struct Sortby { } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub enum Direction { #[serde(rename = "asc")] Ascending, diff --git a/stac/CHANGELOG.md b/stac/CHANGELOG.md index 04dc28f8..1e39fd89 100644 --- a/stac/CHANGELOG.md +++ b/stac/CHANGELOG.md @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Changed + +- Use `geojson::Geometry` instead of a crate-specific `Geometry` type([#245](https://github.com/stac-utils/stac-rs/pull/245)) + +### Removed + +- `schemars` feature ([#245](https://github.com/stac-utils/stac-rs/pull/245)) + ## [0.6.0] - 2024-04-11 ### Added diff --git a/stac/Cargo.toml b/stac/Cargo.toml index 85f2094e..bad16586 100644 --- a/stac/Cargo.toml +++ b/stac/Cargo.toml @@ -12,9 +12,8 @@ categories = ["science", "data-structures"] [features] gdal = ["dep:gdal", "dep:gdal-sys", "dep:log"] -geo = ["dep:geo", "dep:geojson"] +geo = ["dep:geo"] reqwest = ["dep:reqwest"] -schemars = ["dep:schemars"] [dependencies] chrono = "0.4" @@ -25,10 +24,9 @@ gdal-sys = { version = "0.9", optional = true, features = [ "bindgen", ] } # we use bindgen b/c the gdal crate doesn't support GDAL 3.8 as of this writing, and we depend on gdal-sys for build script usage geo = { version = "0.28", optional = true } -geojson = { version = "0.24", optional = true } +geojson = { version = "0.24" } log = { version = "0.4", optional = true } reqwest = { version = "0.12", optional = true, features = ["json", "blocking"] } -schemars = { version = "0.8", optional = true } serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["preserve_order"] } thiserror = "1" diff --git a/stac/README.md b/stac/README.md index 920ee648..670c3585 100644 --- a/stac/README.md +++ b/stac/README.md @@ -33,7 +33,7 @@ Please see the [documentation](https://docs.rs/stac) for more usage examples. ## Features -There are four opt-in features. +There are a few opt-in features. ### reqwest @@ -110,16 +110,6 @@ Then, you can set an item's geometry and bounding box at the same time: } ``` -### schemars - -`schemars` allows for [jsonschema](https://json-schema.org/) generation from STAC objects. -This is mostly useful for auto-generating OpenAPI documentation for STAC APIs. - -```toml -[dependencies] -stac = { version = "0.6", features = ["schemars"]} -``` - ## Other info This crate is part of the [stac-rs](https://github.com/stac-utils/stac-rs) monorepo, see its README for contributing and license information. diff --git a/stac/src/asset.rs b/stac/src/asset.rs index abff44c0..3bcaa10a 100644 --- a/stac/src/asset.rs +++ b/stac/src/asset.rs @@ -5,7 +5,6 @@ use std::collections::HashMap; /// An Asset is an object that contains a URI to data associated with the [Item](crate::Item) that can be downloaded or streamed. #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Asset { /// URI to the asset object. /// diff --git a/stac/src/bounds.rs b/stac/src/bounds.rs index 87942229..edf0f679 100644 --- a/stac/src/bounds.rs +++ b/stac/src/bounds.rs @@ -1,3 +1,5 @@ +use geojson::{Geometry, Value}; + /// Two-dimensional bounds. #[derive(Debug, Clone, Copy, PartialEq)] pub struct Bounds { @@ -62,6 +64,29 @@ impl Bounds { self.xmax = self.xmax.max(other.xmax); self.ymax = self.ymax.max(other.ymax); } + + /// Converts this bounds to a [Geometry](geojson::Geometry). + /// + /// # Examples + /// + /// ``` + /// use stac::Bounds; + /// let bounds = Bounds::new(1., 1., 2., 2.); + /// let geomtry = bounds.to_geometry(); + /// ``` + pub fn to_geometry(&self) -> Geometry { + Geometry { + bbox: None, + value: Value::Polygon(vec![vec![ + vec![self.xmin, self.ymin], + vec![self.xmax, self.ymin], + vec![self.xmax, self.ymax], + vec![self.xmax, self.ymax], + vec![self.xmin, self.ymin], + ]]), + foreign_members: None, + } + } } impl Default for Bounds { diff --git a/stac/src/catalog.rs b/stac/src/catalog.rs index adbe8d24..4228373b 100644 --- a/stac/src/catalog.rs +++ b/stac/src/catalog.rs @@ -18,7 +18,6 @@ pub const CATALOG_TYPE: &str = "Catalog"; /// Their purpose is discovery: to be browsed by people or be crawled by clients /// to build a searchable index. #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Catalog { /// Set to `"Catalog"` if this Catalog only implements the `Catalog` spec. #[serde( diff --git a/stac/src/collection.rs b/stac/src/collection.rs index 465c355c..db3341ca 100644 --- a/stac/src/collection.rs +++ b/stac/src/collection.rs @@ -21,7 +21,6 @@ const DEFAULT_LICENSE: &str = "proprietary"; /// contains all the required fields is a valid STAC `Collection` and also a valid /// STAC `Catalog`. #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Collection { /// Must be set to `"Collection"` to be a valid `Collection`. #[serde( @@ -99,7 +98,6 @@ pub struct Collection { /// data offered by this `Collection`. May also include information about the /// final storage provider hosting the data. #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Provider { /// The name of the organization or the individual. pub name: String, @@ -129,7 +127,6 @@ pub struct Provider { /// The object describes the spatio-temporal extents of the [Collection](crate::Collection). #[derive(Debug, Default, Serialize, Deserialize, PartialEq, Clone)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Extent { /// Spatial extents covered by the `Collection`. pub spatial: SpatialExtent, @@ -143,7 +140,6 @@ pub struct Extent { /// The object describes the spatial extents of the Collection. #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct SpatialExtent { /// Potential spatial extents covered by the Collection. pub bbox: Vec>, @@ -151,7 +147,6 @@ pub struct SpatialExtent { /// The object describes the temporal extents of the Collection. #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct TemporalExtent { /// Potential temporal extents covered by the Collection. pub interval: Vec<[Option; 2]>, diff --git a/stac/src/extensions/projection.rs b/stac/src/extensions/projection.rs index d01eb45a..37909955 100644 --- a/stac/src/extensions/projection.rs +++ b/stac/src/extensions/projection.rs @@ -1,11 +1,10 @@ //! The Projection extension. -use crate::Geometry; +use super::Extension; +use geojson::Geometry; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; -use super::Extension; - /// The projection extension fields. #[derive(Debug, Serialize, Deserialize, Default, PartialEq, Clone)] pub struct Projection { diff --git a/stac/src/gdal.rs b/stac/src/gdal.rs index 0b783977..c8087f50 100644 --- a/stac/src/gdal.rs +++ b/stac/src/gdal.rs @@ -6,7 +6,7 @@ use crate::{ raster::{Band, Raster, Statistics}, Projection, }, - Asset, Bounds, Extensions, Geometry, Item, Result, + Asset, Bounds, Extensions, Item, Result, }; use gdal::{ spatial_ref::{CoordTransform, SpatialRef}, @@ -50,12 +50,7 @@ pub fn update_item( } } if bounds.is_valid() { - item.geometry = Some(Geometry::rect( - bounds.xmin, - bounds.ymin, - bounds.xmax, - bounds.ymax, - )); + item.geometry = Some(bounds.to_geometry()); item.bbox = Some(vec![bounds.xmin, bounds.ymin, bounds.xmax, bounds.ymax]); } if has_projection { diff --git a/stac/src/geometry.rs b/stac/src/geometry.rs deleted file mode 100644 index c981f83f..00000000 --- a/stac/src/geometry.rs +++ /dev/null @@ -1,104 +0,0 @@ -use serde::{Deserialize, Serialize}; -use serde_json::{json, Map, Value}; - -#[cfg(feature = "geo")] -use crate::{Error, Result}; - -/// Additional metadata fields can be added to the GeoJSON Object Properties. -/// -/// We can't just use the [geojson] crate because it doesn't implement [schemars]. -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] -pub struct Geometry { - /// The geometry type. - pub r#type: String, - - /// The other geometry attributes. - /// - /// `GeometryCollection` doesn't have a `coordinates` member, so we must - /// capture everything in a flat, generic array. - #[serde(flatten)] - pub attributes: Map, -} - -impl Geometry { - /// Creates a point geometry. - /// - /// # Examples - /// - /// ``` - /// use stac::Geometry; - /// let geometry = Geometry::point(-108.0, 42.0); - /// ``` - pub fn point(x: f64, y: f64) -> Geometry { - let mut attributes = Map::new(); - let _ = attributes.insert("coordinates".to_string(), json!([x, y])); - Geometry { - r#type: "Point".to_string(), - attributes, - } - } - - /// Creates a geometry. - /// - /// # Examples - /// - /// ``` - /// use stac::Geometry; - /// let geometry = Geometry::rect(-108.0, 42.0, -107.0, 43.0); - /// ``` - pub fn rect(xmin: f64, ymin: f64, xmax: f64, ymax: f64) -> Geometry { - let mut attributes = Map::new(); - let _ = attributes.insert( - "coordinates".to_string(), - json!([[ - [xmin, ymin], - [xmax, ymin], - [xmax, ymax], - [xmin, ymax], - [xmin, ymin] - ]]), - ); - Geometry { - r#type: "Polygon".to_string(), - attributes, - } - } -} - -#[cfg(feature = "geo")] -impl TryFrom for geo::Geometry { - type Error = Error; - fn try_from(geometry: Geometry) -> Result { - serde_json::from_value::(serde_json::to_value(geometry)?)? - .try_into() - .map_err(Error::from) - } -} - -#[cfg(all(test, feature = "geo"))] -mod tests { - use geo::{algorithm::orient::Direction, Orient, Point, Polygon, Rect}; - - #[test] - fn point() { - let point = super::Geometry::point(-108.0, 42.0); - let geometry: geo::Geometry = point.try_into().unwrap(); - assert_eq!(geometry, geo::Geometry::Point(Point::new(-108.0, 42.0))); - } - - #[test] - fn rect() { - let rect = super::Geometry::rect(-108.0, 42.0, -107.0, 43.0); - let geometry: geo::Geometry = rect.try_into().unwrap(); - assert_eq!( - Polygon::try_from(geometry).unwrap(), - Rect::new( - geo::coord! { x: -108.0, y: 42.0 }, - geo::coord! { x: -107.0, y: 43.0 }, - ) - .to_polygon() - .orient(Direction::Default) - ); - } -} diff --git a/stac/src/item.rs b/stac/src/item.rs index 4188c96e..8e629171 100644 --- a/stac/src/item.rs +++ b/stac/src/item.rs @@ -1,9 +1,8 @@ //! STAC Items. -use crate::{ - Asset, Assets, Error, Extensions, Fields, Geometry, Href, Link, Links, Result, STAC_VERSION, -}; +use crate::{Asset, Assets, Error, Extensions, Fields, Href, Link, Links, Result, STAC_VERSION}; use chrono::{DateTime, FixedOffset, Utc}; +use geojson::Geometry; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; use std::{collections::HashMap, path::Path}; @@ -361,7 +360,7 @@ impl Item { /// assert_eq!(item.bbox.unwrap(), vec![-105.1, 41.1, -105.1, 41.1]); /// ``` #[cfg(feature = "geo")] - pub fn set_geometry(&mut self, geometry: impl Into>) -> Result<()> { + pub fn set_geometry(&mut self, geometry: impl Into>) -> Result<()> { use geo::BoundingRect; let geometry = geometry.into(); diff --git a/stac/src/lib.rs b/stac/src/lib.rs index 5907043c..82c7ec7b 100644 --- a/stac/src/lib.rs +++ b/stac/src/lib.rs @@ -128,7 +128,6 @@ mod fields; pub mod gdal; #[cfg(feature = "geo")] pub mod geo; -mod geometry; mod href; mod io; pub mod item; @@ -145,7 +144,6 @@ pub use { error::Error, extensions::{Extension, Extensions}, fields::Fields, - geometry::Geometry, href::{href_to_url, Href}, io::{read, read_json}, item::{Item, Properties, ITEM_TYPE}, diff --git a/stac/src/link.rs b/stac/src/link.rs index 605d8956..b0e9444a 100644 --- a/stac/src/link.rs +++ b/stac/src/link.rs @@ -32,7 +32,6 @@ pub const COLLECTION_REL: &str = "collection"; /// crate](https://github.com/stac-utils/stac-rs/stac-api), but in this case it /// was simpler to include these attributes in the base [Link] rather to create a new one. #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Link { /// The actual link in the format of an URL. ///