My situation
When I use serde
to serialize/deserialize data, I want to skip serializing empty fields. I do this:
#[derive(Default, Serialize, Deserialize)]
struct MyData {
pub mandatory_field: i32,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub optional_string: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub optional_array: Vec<i32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub optional_value: Option<i32>,
}
It is manageable with built-in data structures, but with custom types, I have to make my own is_empty
:
#[derive(Default, Serialize, Deserialize)]
struct MyData {
pub mandatory_field: i32,
#[serde(default, skip_serializing_if = "OptionalData::is_empty")]
pub optional_data: OptionalData,
}
#[derive(Default, Serialize, Deserialize)]
struct OptionalData {
#[serde(default, skip_serializing_if = "String::is_empty")]
pub optional_string: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub optional_array: Vec<i32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub optional_value: Option<i32>,
}
impl OptionalData {
pub fn is_empty(&self) -> bool {
self.optional_string.is_empty() && self.optional_array.is_empty() && self.optional_value.is_none()
}
}
Proposal
Add a trait named IsZero
and a derive macro named IsZero
. The above code could be simplified into:
#[derive(Default, Serialize, Deserialize)]
struct MyData {
pub mandatory_field: i32,
#[serde(default, skip_serializing_if = "IsZero::is_zero")]
pub optional_data: OptionalData,
}
#[derive(Default, Serialize, Deserialize, IsZero)]
struct OptionalData {
#[serde(default, skip_serializing_if = "IsZero::is_zero")]
pub optional_string: String,
#[serde(default, skip_serializing_if = "IsZero::is_zero")]
pub optional_array: Vec<i32>,
#[serde(default, skip_serializing_if = "IsZero::is_zero")]
pub optional_value: Option<i32>,
}
Alternatively, instead of IsZero
, we should have a trait named Zero
that both create "zero" value and check if a value is "zero" (I am assuming that Default
trait doesn't always return "zero").