There is a serialization inconsistency between oci-spec-go and oci-spec-rs regarding empty Maps and Vectors.
oci-spec-go: Skips serialization for empty collections due to the omitempty tag.
oci-spec-rs: Still serializes empty collections because it only uses #[serde(skip_serializing_if = "Option::is_none")], which doesn't account for empty states."
To address this, there are two potential solutions:
- Add a custom skip function: Introduce a helper function for
skip_serializing_if that checks if the collection is either None or empty. This maintains the current structure but aligns the output with Go's omitempty.
fn is_option_map_empty(opt: &Option<HashMap<String, String>>) -> bool {
opt.as_ref().map_or(true, |m| m.is_empty())
}
pub struct State {
/// annotations are key values associated with the container.
#[serde(default, skip_serializing_if = "is_option_map_empty")]
annotations: Option<HashMap<String, String>>,
}
- Remove the
Option wrapper: Drop the Option and use HashMap or Vec directly with #[serde(default, skip_serializing_if = "HashMap::is_empty")]. While this makes the code cleaner and more "Rust-idiomatic," it would be a breaking change for users of this crate.
pub struct State {
/// annotations are key values associated with the container.
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
annotations: HashMap<String, String>,
}
I believe using a helper function is the more reasonable approach since removing the Option would have a significant impact as a breaking change. However, if using Option for collections is considered unidiomatic in Rust, I’m also open to the latter option. Which approach would you prefer?
There is a serialization inconsistency between
oci-spec-goandoci-spec-rsregarding empty Maps and Vectors.oci-spec-go: Skips serialization for empty collections due to theomitemptytag.oci-spec-rs: Still serializes empty collections because it only uses#[serde(skip_serializing_if = "Option::is_none")], which doesn't account for empty states."To address this, there are two potential solutions:
skip_serializing_ifthat checks if the collection is eitherNoneor empty. This maintains the current structure but aligns the output with Go'somitempty.Optionwrapper: Drop theOptionand useHashMaporVecdirectly with#[serde(default, skip_serializing_if = "HashMap::is_empty")]. While this makes the code cleaner and more "Rust-idiomatic," it would be a breaking change for users of this crate.I believe using a helper function is the more reasonable approach since removing the
Optionwould have a significant impact as a breaking change. However, if usingOptionfor collections is considered unidiomatic in Rust, I’m also open to the latter option. Which approach would you prefer?