Crate serde_with
source ·Expand description
This crate provides custom de/serialization helpers to use in combination with serde’s with-annotation and with the improved serde_as-annotation.
Some common use cases are:
- De/Serializing a type using the
DisplayandFromStrtraits, e.g., foru8,url::Url, ormime::Mime. CheckDisplayFromStrfor details. - Support for arrays larger than 32 elements or using const generics.
With
serde_aslarge arrays are supported, even if they are nested in other types.[bool; 64],Option<[u8; M]>, andBox<[[u8; 64]; N]>are all supported, as this examples shows. - Skip serializing all empty
Optiontypes with#[skip_serializing_none]. - Apply a prefix to each field name of a struct, without changing the de/serialize implementations of the struct using
with_prefix!. - Deserialize a comma separated list like
#hash,#tags,#are,#greatinto aVec<String>. Check the documentation forserde_with::StringWithSeparator::<CommaSeparator, T>.
Getting Help
Check out the user guide to find out more tips and tricks about this crate.
For further help using this crate you can open a new discussion or ask on users.rust-lang.org. For bugs, please open a new issue on GitHub.
Use serde_with in your Project
# Add the current version to your Cargo.toml
cargo add serde_with
The crate contains different features for integration with other common crates. Check the feature flags section for information about all available features.
Examples
Annotate your struct or enum to enable the custom de/serializer.
The #[serde_as] attribute must be placed before the #[derive].
The as is analogous to the with attribute of serde.
You mirror the type structure of the field you want to de/serialize.
You can specify converters for the inner types of a field, e.g., Vec<DisplayFromStr>.
The default de/serialization behavior can be restored by using _ as a placeholder, e.g., BTreeMap<_, DisplayFromStr>.
DisplayFromStr
#[serde_as]
#[derive(Deserialize, Serialize)]
struct Foo {
// Serialize with Display, deserialize with FromStr
#[serde_as(as = "DisplayFromStr")]
bar: u8,
}
// This will serialize
Foo {bar: 12}
// into this JSON
{"bar": "12"}Large and const-generic arrays
serde does not support arrays with more than 32 elements or using const-generics.
The serde_as attribute allows circumventing this restriction, even for nested types and nested arrays.
On top of it, [u8; N] (aka, bytes) can use the specialized "Bytes" for efficiency much like the serde_bytes crate.
#[serde_as]
#[derive(Deserialize, Serialize)]
struct Arrays<const N: usize, const M: usize> {
#[serde_as(as = "[_; N]")]
constgeneric: [bool; N],
#[serde_as(as = "Box<[[_; 64]; N]>")]
nested: Box<[[u8; 64]; N]>,
#[serde_as(as = "Option<[_; M]>")]
optional: Option<[u8; M]>,
#[serde_as(as = "Bytes")]
bytes: [u8; M],
}
// This allows us to serialize a struct like this
let arrays: Arrays<100, 128> = Arrays {
constgeneric: [true; 100],
nested: Box::new([[111; 64]; 100]),
optional: Some([222; 128]),
bytes: [0x42; 128],
};
assert!(serde_json::to_string(&arrays).is_ok());skip_serializing_none
This situation often occurs with JSON, but other formats also support optional fields.
If many fields are optional, putting the annotations on the structs can become tedious.
The #[skip_serializing_none] attribute must be placed before the #[derive].
#[skip_serializing_none]
#[derive(Deserialize, Serialize)]
struct Foo {
a: Option<usize>,
b: Option<usize>,
c: Option<usize>,
d: Option<usize>,
e: Option<usize>,
f: Option<usize>,
g: Option<usize>,
}
// This will serialize
Foo {a: None, b: None, c: None, d: Some(4), e: None, f: None, g: Some(7)}
// into this JSON
{"d": 4, "g": 7}Advanced serde_as usage
This example is mainly supposed to highlight the flexibility of the serde_as-annotation compared to serde’s with-annotation.
More details about serde_as can be found in the user guide.
use std::time::Duration;
#[serde_as]
#[derive(Deserialize, Serialize)]
enum Foo {
Durations(
// Serialize them into a list of number as seconds
#[serde_as(as = "Vec<DurationSeconds>")]
Vec<Duration>,
),
Bytes {
// We can treat a Vec like a map with duplicates.
// JSON only allows string keys, so convert i32 to strings
// The bytes will be hex encoded
#[serde_as(as = "Map<DisplayFromStr, Hex>")]
bytes: Vec<(i32, Vec<u8>)>,
}
}
// This will serialize
Foo::Durations(
vec![Duration::new(5, 0), Duration::new(3600, 0), Duration::new(0, 0)]
)
// into this JSON
{
"Durations": [5, 3600, 0]
}
// and serializes
Foo::Bytes {
bytes: vec![
(1, vec![0, 1, 2]),
(-100, vec![100, 200, 255]),
(1, vec![0, 111, 222]),
],
}
// into this JSON
{
"Bytes": {
"bytes": {
"1": "000102",
"-100": "64c8ff",
"1": "006fde"
}
}
}Modules
- Module for
DeserializeAsimplementations - Specify the format and how lenient the deserialization is
- De/Serialization for Rust’s builtin and std types
- Module for
SerializeAsimplementations
Macros
- Support deserializing from flattened and non-flattened representation
- Create new conversion adapters from functions
- Serialize with an added prefix on every field name and deserialize by trimming away the prefix.
Structs
- Adapter to convert from
serde_asto the serde traits. - Deserialize a boolean from a number
- Borrow
Cowdata during deserialization when possible. - Optimized handling of owned and borrowed byte representations.
- Deserialize from bytes or string
- Deserialize value and return
Defaulton error - Deserialize
Defaultfromnullvalues - Equivalent to
DurationSecondswith micro-seconds as base unit. - Equivalent to
DurationSecondsWithFracwith micro-seconds as base unit. - Equivalent to
DurationSecondswith milli-seconds as base unit. - Equivalent to
DurationSecondsWithFracwith milli-seconds as base unit. - Equivalent to
DurationSecondswith nano-seconds as base unit. - Equivalent to
DurationSecondsWithFracwith nano-seconds as base unit. - De/Serialize Durations as number of seconds.
- De/Serialize Durations as number of seconds.
- Represent a list of enum values as a map.
- Serialize value by converting to/from a proxy type with serde support.
- Convert
Vecelements into key-value map entries - This serializes a list of tuples into a map
- Ensure that the last value is taken, if duplicate values exist
- Ensure no duplicate keys exist in a map.
- De/Serialize a
Option<String>type while transforming the empty string toNone - Deserialize one or many elements
- Try multiple deserialization options until one succeeds.
- Adapter to convert from
serde_asto the serde traits. - De/Serialize a Map into a list of tuples
- Ensure that the last value is taken, if duplicate values exist
- Ensure no duplicate values exist in a set.
- Equivalent to
TimestampSecondswith micro-seconds as base unit. - Equivalent to
TimestampSecondsWithFracwith micro-seconds as base unit. - Equivalent to
TimestampSecondswith milli-seconds as base unit. - Equivalent to
TimestampSecondsWithFracwith milli-seconds as base unit. - Equivalent to
TimestampSecondswith nano-seconds as base unit. - Equivalent to
TimestampSecondsWithFracwith nano-seconds as base unit. - De/Serialize timestamps as seconds since the UNIX epoch
- De/Serialize timestamps as seconds since the UNIX epoch
- Serialize value by converting to/from a proxy type with serde support.
- Deserialize a sequence into
Vec<T>, skipping elements which fail to deserialize.
Traits
- A data structure that can be deserialized from any data format supported by Serde, analogue to
Deserialize. - A data structure that can be serialized into any data format supported by Serde, analogue to
Serialize.
Attribute Macros
- Apply attributes to all fields with matching types
- Convenience macro to use the
serde_assystem. - Add
skip_serializing_ifannotations to [Option] fields.