Macro serde_with::serde_conv
source · [−]macro_rules! serde_conv {
($m:ident, $t:ty, $ser:expr, $de:expr) => { ... };
($vis:vis $m:ident, $t:ty, $ser:expr, $de:expr) => { ... };
}
Expand description
Create new conversion adapters from functions
The macro lets you create a new converter, which is usable for serde’s with-attribute and #[serde_as]
.
Its main use case is to write simple converters for types which are not serializable.
Another use-case is to change the serialization behavior if the implemented Serialize
/Deserialize
trait is insufficient.
The macro takes four arguments:
- The name of the converter type.
The type can be prefixed with a visibility modifies like
pub
orpub(crate)
. By default the type is not marked as public (pub(self)
). - The type
T
we want to extend with custom behavior. - A function or macro taking a
&T
and returning a serializable type. - A function or macro taking a deserializable type and returning a
Result<T, E>
. The error typeE
must implementDisplay
.
Example
In this example we write custom serialization behavior for a Rgb
type.
We want to serialize it as a [u8; 3]
.
#[derive(Clone, Copy, Debug, PartialEq)]
struct Rgb {
red: u8,
green: u8,
blue: u8,
}
serde_with::serde_conv!(
RgbAsArray,
Rgb,
|rgb: &Rgb| [rgb.red, rgb.green, rgb.blue],
|value: [u8; 3]| -> Result<_, std::convert::Infallible> {
Ok(Rgb {
red: value[0],
green: value[1],
blue: value[2],
})
}
);
//////////////////////////////////////////////////
// We define some colors to be used later
let green = Rgb {red: 0, green: 255, blue: 0};
let orange = Rgb {red: 255, green: 128, blue: 0};
let pink = Rgb {red: 255, green: 0, blue: 255};
//////////////////////////////////////////////////
// We can now use the `RgbAsArray` adapter with `serde_as`.
#[serde_with::serde_as]
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Colors {
#[serde_as(as = "RgbAsArray")]
one_rgb: Rgb,
#[serde_as(as = "Vec<RgbAsArray>")]
rgbs_in_vec: Vec<Rgb>,
}
let data = Colors {
one_rgb: orange,
rgbs_in_vec: vec![green, pink],
};
let json = serde_json::json!({
"one_rgb": [255, 128, 0],
"rgbs_in_vec": [
[0, 255, 0],
[255, 0, 255]
]
});
assert_eq!(json, serde_json::to_value(&data).unwrap());
assert_eq!(data, serde_json::from_value(json).unwrap());
//////////////////////////////////////////////////
// The types generated by `serde_conv` is also compatible with serde's with attribute
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct ColorsWith {
#[serde(with = "RgbAsArray")]
rgb_with: Rgb,
}
let data = ColorsWith {
rgb_with: pink,
};
let json = serde_json::json!({
"rgb_with": [255, 0, 255]
});
assert_eq!(json, serde_json::to_value(&data).unwrap());
assert_eq!(data, serde_json::from_value(json).unwrap());