Expand description

crates.io badge Build Status codecov CII Best Practices Binder


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 Display and FromStr traits, e.g., for u8, url::Url, or mime::Mime. Check DisplayFromStr or serde_with::rust::display_fromstr for details.
  • Support for arrays larger than 32 elements or using const generics. With serde_as large arrays are supported, even if they are nested in other types. [bool; 64], Option<[u8; M]>, and Box<[[u8; 64]; N]> are all supported, as this examples shows.
  • Skip serializing all empty Option types 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,#great into a Vec<String>. Check the documentation for serde_with::rust::StringWithSeparator::<CommaSeparator>.

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 this to your Cargo.toml:

[dependencies.serde_with]
version = "1.14.0"
features = [ "..." ]

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 place before the #[derive].

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.

#[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]>,
}

// 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])
};
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 place 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.

#[serde_as]
#[derive(Deserialize, Serialize)]
struct Foo {
     // Serialize them into a list of number as seconds
     #[serde_as(as = "Vec<DurationSeconds>")]
     durations: Vec<Duration>,
     // 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 = "BTreeMap<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)],
    bytes: vec![
        (1, vec![0, 1, 2]),
        (-100, vec![100, 200, 255]),
        (1, vec![0, 111, 222]),
    ],
}

// into this JSON
{
    "durations": [5, 3600, 0],
    "bytes": {
        "1": "000102",
        "-100": "64c8ff",
        "1": "006fde"
    }
}

Modules

base64base64

De/Serialization of base64 encoded bytes

chronochrono

De/Serialization of chrono types

Module for DeserializeAs implementations

Specify the format and how lenient the deserialization is

serde_with User Guide

hexhex

De/Serialization of hexadecimal encoded bytes

jsonjson

De/Serialization of JSON

De/Serialization for Rust’s builtin and std types

Module for SerializeAs implementations

time_0_3time_0_3

De/Serialization of time v0.3 types

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_as to the serde traits.

Deserialize a boolean from a number

Borrow Cow data during deserialization when possible.

Optimized handling of owned and borrowed byte representations.

Deserialize from bytes or string

Predefined separator using a single comma

Deserialize value and return Default on error

Deserialize Default from null values

De/Serialize using Display and FromStr implementation

Equivalent to DurationSeconds with micro-seconds as base unit.

Equivalent to DurationSecondsWithFrac with micro-seconds as base unit.

Equivalent to DurationSeconds with milli-seconds as base unit.

Equivalent to DurationSecondsWithFrac with milli-seconds as base unit.

Equivalent to DurationSeconds with nano-seconds as base unit.

Equivalent to DurationSecondsWithFrac with 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.

De/Serialize a Option<String> type while transforming the empty string to None

Deserialize one or many elements

Try multiple deserialization options until one succeeds.

Adapter to convert from serde_as to the serde traits.

Predefined separator using a single space

De/Serialize a delimited collection using Display and FromStr implementation

Equivalent to TimestampSeconds with micro-seconds as base unit.

Equivalent to TimestampSecondsWithFrac with micro-seconds as base unit.

Equivalent to TimestampSeconds with milli-seconds as base unit.

Equivalent to TimestampSecondsWithFrac with milli-seconds as base unit.

Equivalent to TimestampSeconds with nano-seconds as base unit.

Equivalent to TimestampSecondsWithFrac with 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.

Separator for string-based collection de/serialization

A data structure that can be serialized into any data format supported by Serde, analogue to Serialize.

Attribute Macros

Convenience macro to use the serde_as system.

Add skip_serializing_if annotations to Option fields.

Derive Macros

Deserialize value by using its FromStr implementation

Serialize value by using it’s Display implementation