Attribute Macro serde_with::skip_serializing_none
source · [−]#[skip_serializing_none]
Expand description
Add skip_serializing_if
annotations to Option
fields.
The attribute can be added to structs and enums.
Import this attribute with use serde_with::skip_serializing_none;
.
Example
JSON APIs sometimes have many optional values. Missing values should not be serialized, to keep the serialized format smaller. Such a data type might look like:
#[derive(Serialize)]
struct Data {
#[serde(skip_serializing_if = "Option::is_none")]
a: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
b: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
c: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
d: Option<bool>,
}
The skip_serializing_if
annotation is repetitive and harms readability.
Instead, the same struct can be written as:
#[skip_serializing_none]
#[derive(Serialize)]
struct Data {
a: Option<String>,
b: Option<u64>,
c: Option<String>,
// Always serialize field d even if None
#[serialize_always]
d: Option<bool>,
}
Existing skip_serializing_if
annotations will not be altered.
If some values should always be serialized, then the serialize_always
can be used.
Limitations
The serialize_always
cannot be used together with a manual skip_serializing_if
annotations, as these conflict in their meaning.
A compile error will be generated if this occurs.
The skip_serializing_none
only works if the type is called Option
, std::option::Option
, or core::option::Option
.
Type aliasing an Option
and giving it another name, will cause this field to be ignored.
This cannot be supported, as proc-macros run before type checking, thus it is not possible to determine if a type alias refers to an Option
.
type MyOption<T> = Option<T>;
#[skip_serializing_none]
#[derive(Serialize)]
struct Data {
a: MyOption<String>, // This field will not be skipped
}
Likewise, if you import a type and name it Option
, the skip_serializing_if
attributes will be added and compile errors will occur, if Option::is_none
is not a valid function.
Here the function Vec::is_none
does not exist and therefore the example fails to compile.
use std::vec::Vec as Option;
#[skip_serializing_none]
#[derive(Serialize)]
struct Data {
a: Option<String>,
}