Expand description

De/Serialize Transformations Available

This page lists the transformations implemented in this crate and supported by serde_as.

  1. Base64 encode bytes
  2. Big Array support
  3. bool from integer
  4. Borrow from the input for Cow type
  5. Bytes with more efficiency
  6. Convert to an intermediate type using Into
  7. Convert to an intermediate type using TryInto
  8. Default from null
  9. De/Serialize into Vec, ignoring errors
  10. De/Serialize with FromStr and Display
  11. Duration as seconds
  12. Hex encode bytes
  13. Ignore deserialization errors
  14. Maps to Vec of enums
  15. Maps to Vec of tuples
  16. NaiveDateTime like UTC timestamp
  17. None as empty String
  18. One or many elements into Vec
  19. Pick first successful deserialization
  20. Timestamps as seconds since UNIX epoch
  21. Value into JSON String
  22. Vec of tuples to Maps
  23. Well-known time formats for OffsetDateTime

Base64 encode bytes

Base64

Requires the base64 feature. The character set and padding behavior can be configured.

// Rust
#[serde_as(as = "serde_with::base64::Base64")]
value: Vec<u8>,
#[serde_as(as = "Base64<Bcrypt, Unpadded>")]
bcrypt_unpadded: Vec<u8>,

// JSON
"value": "SGVsbG8gV29ybGQ=",
"bcrypt_unpadded": "QETqZE6eT07wZEO",

Big Array support

Support for arrays of arbitrary size.

// Rust
#[serde_as(as = "[[_; 64]; 33]")]
value: [[u8; 64]; 33],

// JSON
"value": [[0,0,0,0,0,...], [0,0,0,...], ...],

bool from integer

Deserialize an integer and convert it into a bool. BoolFromInt<Strict> (default) deserializes 0 to false and 1 to true, other numbers are errors. BoolFromInt<Flexible> deserializes any non-zero as true. Serialization only emits 0/1.

// Rust
#[serde_as(as = "BoolFromInt")] // BoolFromInt<Strict>
b: bool,

// JSON
"b": 1,

Borrow from the input for Cow type

The types Cow<'_, str>, Cow<'_, [u8]>, or Cow<'_, [u8; N]> can borrow from the input, avoiding extra copies.

// Rust
#[serde_as(as = "BorrowCow")]
value: Cow<'a, str>,

// JSON
"value": "foobar",

Bytes with more efficiency

Bytes

More efficient serialization for byte slices and similar.

// Rust
#[serde_as(as = "Bytes")]
value: Vec<u8>,

// JSON
"value": [0, 1, 2, 3, ...],

Convert to an intermediate type using Into

FromInto

// Rust
#[serde_as(as = "FromInto<(u8, u8, u8)>")]
value: Rgb,

impl From<(u8, u8, u8)> for Rgb { ... }
impl From<Rgb> for (u8, u8, u8) { ... }

// JSON
"value": [128, 64, 32],

Convert to an intermediate type using TryInto

TryFromInto

// Rust
#[serde_as(as = "TryFromInto<i8>")]
value: u8,

// JSON
"value": 127,

Default from null

DefaultOnNull

// Rust
#[serde_as(as = "DefaultOnNull")]
value: u32,
#[serde_as(as = "DefaultOnNull<DisplayFromStr>")]
value2: u32,

// JSON
"value": 123,
"value2": "999",

// Deserializes null into the Default value, i.e.,
null => 0

De/Serialize into Vec, ignoring errors

VecSkipError

For formats with heterogenous-typed sequences, we can collect only the deserializable elements. This is also useful for unknown enum variants.

#[derive(serde::Deserialize)]
enum Color {
    Red,
    Green,
    Blue,
}

// JSON
"colors": ["Blue", "Yellow", "Green"],

// Rust
#[serde_as(as = "VecSkipError<_>")]
colors: Vec<Color>,

// => vec![Blue, Green]

De/Serialize with FromStr and Display

Useful if a type implements FromStr / Display but not Deserialize / Serialize.

DisplayFromStr

// Rust
#[serde_as(as = "serde_with::DisplayFromStr")]
value: u128,
#[serde_as(as = "serde_with::DisplayFromStr")]
mime: mime::Mime,

// JSON
"value": "340282366920938463463374607431768211455",
"mime": "text/*",

Duration as seconds

DurationSeconds

// Rust
#[serde_as(as = "serde_with::DurationSeconds<u64>")]
value: Duration,

// JSON
"value": 86400,

DurationSecondsWithFrac supports subsecond precision:

// Rust
#[serde_as(as = "serde_with::DurationSecondsWithFrac<f64>")]
value: Duration,

// JSON
"value": 1.234,

Different serialization formats are possible:

// Rust
#[serde_as(as = "serde_with::DurationSecondsWithFrac<String>")]
value: Duration,

// JSON
"value": "1.234",

The same conversions are also implemented for chrono::Duration with the chrono feature.

The same conversions are also implemented for time::Duration with the time_0_3 feature.

Hex encode bytes

Hex

Requires the hex feature. The hex string can use upper- and lowercase characters.

// Rust
#[serde_as(as = "serde_with::hex::Hex")]
lowercase: Vec<u8>,
#[serde_as(as = "serde_with::hex::Hex<serde_with::formats::Uppercase>")]
uppercase: Vec<u8>,

// JSON
"lowercase": "deadbeef",
"uppercase": "DEADBEEF",

Ignore deserialization errors

Check the documentation for DefaultOnError.

Maps to Vec of enums

EnumMap

Combine multiple enum values into a single map. The key is the enum variant name, and the value is the variant value. This only works with externally tagged enums, the default enum representation. Other forms cannot be supported.

enum EnumValue {
    Int(i32),
    String(String),
    Unit,
    Tuple(i32, String),
    Struct {
        a: i32,
        b: String,
    },
}

// Rust
struct VecEnumValues (
    #[serde_as(as = "EnumMap")]
    Vec<EnumValue>,
);

VecEnumValues(vec![
    EnumValue::Int(123),
    EnumValue::String("Foo".to_string()),
    EnumValue::Unit,
    EnumValue::Tuple(1, "Bar".to_string()),
    EnumValue::Struct {
        a: 666,
        b: "Baz".to_string(),
    },
])

// JSON
{
  "Int": 123,
  "String": "Foo",
  "Unit": null,
  "Tuple": [
    1,
    "Bar",
  ],
  "Struct": {
    "a": 666,
    "b": "Baz",
  }
}

Maps to Vec of tuples

// Rust
#[serde_as(as = "Seq<(_, _)>")] // also works with Vec
value: HashMap<String, u32>, // also works with other maps like BTreeMap or IndexMap

// JSON
"value": [
    ["hello", 1],
    ["world", 2]
],

The inverse operation is also available.

NaiveDateTime like UTC timestamp

Requires the chrono feature.

// Rust
#[serde_as(as = "chrono::DateTime<chrono::Utc>")]
value: chrono::NaiveDateTime,

// JSON
"value": "1994-11-05T08:15:30Z",
                             ^ Pretend DateTime is UTC

None as empty String

NoneAsEmptyString

// Rust
#[serde_as(as = "serde_with::NoneAsEmptyString")]
value: Option<String>,

// JSON
"value": "", // converts to None

"value": "Hello World!", // converts to Some

One or many elements into Vec

OneOrMany

// Rust
#[serde_as(as = "serde_with::OneOrMany<_>")]
value: Vec<String>,

// JSON
"value": "", // Deserializes single elements

"value": ["Hello", "World!"], // or lists of many

Pick first successful deserialization

PickFirst

// Rust
#[serde_as(as = "serde_with::PickFirst<(_, serde_with::DisplayFromStr)>")]
value: u32,

// JSON
// serialize into
"value": 666,
// deserialize from either
"value": 666,
"value": "666",

Timestamps as seconds since UNIX epoch

TimestampSeconds

// Rust
#[serde_as(as = "serde_with::TimestampSeconds<i64>")]
value: SystemTime,

// JSON
"value": 86400,

TimestampSecondsWithFrac supports subsecond precision:

// Rust
#[serde_as(as = "serde_with::TimestampSecondsWithFrac<f64>")]
value: SystemTime,

// JSON
"value": 1.234,

Different serialization formats are possible:

// Rust
#[serde_as(as = "serde_with::TimestampSecondsWithFrac<String>")]
value: SystemTime,

// JSON
"value": "1.234",

The same conversions are also implemented for chrono::DateTime<Utc>, chrono::DateTime<Local>, and chrono::NaiveDateTime with the chrono feature.

The conversions are available for time::OffsetDateTime and time::PrimitiveDateTime with the time_0_3 feature enabled.

Value into JSON String

Some JSON APIs are weird and return a JSON encoded string in a JSON response

JsonString

Requires the json feature.

// Rust
#[derive(Deserialize, Serialize)]
struct OtherStruct {
    value: usize,
}

#[serde_as(as = "serde_with::json::JsonString")]
value: OtherStruct,

// JSON
"value": "{\"value\":5}",
#[serde_as(as = "JsonString<Vec<(JsonString, _)>>")]
value: BTreeMap<[u8; 2], u32>,

// JSON
{"value":"[[\"[1,2]\",3],[\"[4,5]\",6]]"}

Vec of tuples to Maps

// Rust
#[serde_as(as = "Map<_, _>")] // also works with BTreeMap and HashMap
value: Vec<(String, u32)>,

// JSON
"value": {
    "hello": 1,
    "world": 2
},

This operation is also available for other sequence types. This includes BinaryHeap<(K, V)>, BTreeSet<(K, V)>, HashSet<(K, V)>, LinkedList<(K, V)>, VecDeque<(K, V)>, Option<(K, V)> and [(K, V); N] for all sizes of N.

The inverse operation is also available.

Well-known time formats for OffsetDateTime

time::OffsetDateTime can be serialized in string format in different well-known formats. Three formats are supported, time::format_description::well_known::Rfc2822, time::format_description::well_known::Rfc3339, and time::format_description::well_known::Iso8601.

// Rust
#[serde_as(as = "time::format_description::well_known::Rfc2822")]
rfc_2822: OffsetDateTime,
#[serde_as(as = "time::format_description::well_known::Rfc3339")]
rfc_3339: OffsetDateTime,
#[serde_as(as = "time::format_description::well_known::Iso8601<Config>")]
iso_8601: OffsetDateTime,

// JSON
"rfc_2822": "Fri, 21 Nov 1997 09:55:06 -0600",
"rfc_3339": "1997-11-21T09:55:06-06:00",
"iso_8061": "1997-11-21T09:55:06-06:00",

These conversions are available with the time_0_3 feature flag.