diff --git a/crates/core/CHANGELOG.md b/crates/core/CHANGELOG.md index 5f7e7288..4dbd1053 100644 --- a/crates/core/CHANGELOG.md +++ b/crates/core/CHANGELOG.md @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Added - `version` ([#476](https://github.com/stac-utils/stac-rs/pull/476)) +- Permissive deserialization ([#505](https://github.com/stac-utils/stac-rs/pull/505)) ### Removed diff --git a/crates/core/src/catalog.rs b/crates/core/src/catalog.rs index 08615fd0..e7c10566 100644 --- a/crates/core/src/catalog.rs +++ b/crates/core/src/catalog.rs @@ -18,7 +18,7 @@ use serde_json::{Map, Value}; #[serde(tag = "type")] pub struct Catalog { /// The STAC version the `Catalog` implements. - #[serde(rename = "stac_version")] + #[serde(rename = "stac_version", default)] pub version: Version, /// A list of extension identifiers the `Catalog` implements. @@ -28,6 +28,7 @@ pub struct Catalog { pub extensions: Vec, /// Identifier for the `Catalog`. + #[serde(default)] pub id: String, /// A short descriptive one-line title for the `Catalog`. @@ -37,9 +38,11 @@ pub struct Catalog { /// Detailed multi-line description to fully explain the `Catalog`. /// /// [CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation. + #[serde(default)] pub description: String, /// A list of references to other documents. + #[serde(default)] pub links: Vec, /// Additional fields not part of the Catalog specification. @@ -131,6 +134,7 @@ impl Migrate for Catalog {} mod tests { use super::Catalog; use crate::STAC_VERSION; + use serde_json::json; #[test] fn new() { @@ -157,4 +161,9 @@ mod tests { roundtrip!(catalog, "examples/catalog.json", Catalog); } + + #[test] + fn permissive_deserialization() { + let _: Catalog = serde_json::from_value(json!({})).unwrap(); + } } diff --git a/crates/core/src/collection.rs b/crates/core/src/collection.rs index 21df9b3e..6fda2c4d 100644 --- a/crates/core/src/collection.rs +++ b/crates/core/src/collection.rs @@ -25,7 +25,7 @@ const DEFAULT_LICENSE: &str = "proprietary"; #[serde(tag = "type")] pub struct Collection { /// The STAC version the `Collection` implements. - #[serde(rename = "stac_version")] + #[serde(rename = "stac_version", default)] pub version: Version, /// A list of extension identifiers the `Collection` implements. @@ -35,6 +35,7 @@ pub struct Collection { pub extensions: Vec, /// Identifier for the `Collection` that is unique across the provider. + #[serde(default)] pub id: String, /// A short descriptive one-line title for the `Collection`. @@ -44,6 +45,7 @@ pub struct Collection { /// Detailed multi-line description to fully explain the `Collection`. /// /// [CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation. + #[serde(default)] pub description: String, /// List of keywords describing the `Collection`. @@ -53,6 +55,7 @@ pub struct Collection { /// `Collection`'s license(s), either a SPDX [License /// identifier](https://spdx.org/licenses/), `"various"` if multiple licenses /// apply or `"proprietary"` for all other cases. + #[serde(default)] pub license: String, /// A list of [providers](Provider), which may include all organizations capturing or @@ -64,6 +67,7 @@ pub struct Collection { pub providers: Option>, /// Spatial and temporal extents. + #[serde(default)] pub extent: Extent, /// A map of property summaries, either a set of values, a range of values @@ -72,6 +76,7 @@ pub struct Collection { pub summaries: Option>, /// A list of references to other documents. + #[serde(default)] pub links: Vec, /// Dictionary of asset objects that can be downloaded, each with a unique key. @@ -413,6 +418,7 @@ impl Migrate for Collection {} #[cfg(test)] mod tests { use super::{Collection, Extent, Provider}; + use serde_json::json; mod collection { use super::Collection; @@ -537,4 +543,9 @@ mod tests { Collection ); } + + #[test] + fn permissive_deserialization() { + let _: Collection = serde_json::from_value(json!({})).unwrap(); + } } diff --git a/crates/core/src/item.rs b/crates/core/src/item.rs index ba85518a..77014fd6 100644 --- a/crates/core/src/item.rs +++ b/crates/core/src/item.rs @@ -32,7 +32,7 @@ const TOP_LEVEL_ATTRIBUTES: [&str; 8] = [ #[serde(tag = "type", rename = "Feature")] pub struct Item { /// The STAC version the `Item` implements. - #[serde(rename = "stac_version")] + #[serde(rename = "stac_version", default)] pub version: Version, /// A list of extensions the `Item` implements. @@ -46,6 +46,7 @@ pub struct Item { /// Provider identifier. /// /// The ID should be unique within the [Collection](crate::Collection) that contains the `Item`. + #[serde(default)] pub id: String, /// Defines the full footprint of the asset represented by this item, @@ -66,12 +67,15 @@ pub struct Item { pub bbox: Option, /// A dictionary of additional metadata for the `Item`. + #[serde(default)] pub properties: Properties, /// List of link objects to resources and related URLs. + #[serde(default)] pub links: Vec, /// Dictionary of asset objects that can be downloaded, each with a unique key. + #[serde(default)] pub assets: HashMap, /// The `id` of the STAC [Collection](crate::Collection) this `Item` @@ -675,6 +679,7 @@ mod tests { use super::{Builder, FlatItem, Item}; use crate::{Asset, STAC_VERSION}; use geojson::{feature::Id, Feature}; + use serde_json::json; #[test] fn new() { @@ -869,4 +874,9 @@ mod tests { let flat_item: FlatItem = serde_json::from_value(value).unwrap(); assert_eq!(flat_item.geometry, None); } + + #[test] + fn permissive_deserialization() { + let _: Item = serde_json::from_value(json!({})).unwrap(); + } } diff --git a/crates/core/src/item_collection.rs b/crates/core/src/item_collection.rs index dbcf2cb8..b6fac900 100644 --- a/crates/core/src/item_collection.rs +++ b/crates/core/src/item_collection.rs @@ -12,7 +12,7 @@ pub struct ItemCollection { /// The list of [Items](Item). /// /// The attribute is actually "features", but we rename to "items". - #[serde(rename = "features")] + #[serde(rename = "features", default)] pub items: Vec, /// List of link objects to resources and related URLs. @@ -118,6 +118,7 @@ impl TryFrom for ItemCollection { mod tests { use super::ItemCollection; use crate::Item; + use serde_json::json; #[test] fn item_collection_from_vec() { @@ -130,4 +131,9 @@ mod tests { let items = vec![Item::new("a"), Item::new("b")]; let _ = ItemCollection::from_iter(items.into_iter()); } + + #[test] + fn permissive_deserialization() { + let _: ItemCollection = serde_json::from_value(json!({})).unwrap(); + } }