pub trait SerializeAs<T: ?Sized> {
    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer
; }
Expand description

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

The trait is analogue to the serde::Serialize trait, with the same meaning of input and output arguments. It can and should the implemented using the same code structure as the Serialize trait. As such, the same advice for implementing Serialize applies here.

Differences to Serialize

The trait is only required for container-like types or types implementing specific conversion functions. Container-like types are Vec, BTreeMap, but also Option and Box. Conversion types serialize into a different serde data type. For example, DisplayFromStr uses the Display trait to serialize a String and DurationSeconds converts a Duration into either String or integer values.

This code shows how to implement Serialize for Box:

impl<T> Serialize for Box<T>
where
    T: Serialize,
{
    #[inline]
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        (**self).serialize(serializer)
    }
}

and this code shows how to do the same using SerializeAs:

impl<T, U> SerializeAs<Box<T>> for Box<U>
where
    U: SerializeAs<T>,
{
    fn serialize_as<S>(source: &Box<T>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        SerializeAsWrap::<T, U>::new(source).serialize(serializer)
    }
}

It uses two type parameters, T and U instead of only one and performs the serialization step using the SerializeAsWrap type. The T type is the on the Rust side before serialization, whereas the U type determines how the value will be serialized. These two changes are usually enough to make a container type implement SerializeAs.

SerializeAsWrap is a piece of glue code which turns SerializeAs into a serde compatible datatype, by converting all calls to serialize into serialize_as. This allows us to implement SerializeAs such that it can be applied recursively throughout the whole data structure. This is mostly important for container types, such as Vec or BTreeMap. In a BTreeMap this allows us to specify two different serialization behaviors, one for key and one for value, using the SerializeAs trait.

Implementing a converter Type

This shows a simplified implementation for DisplayFromStr.

struct DisplayFromStr;

impl<T> SerializeAs<T> for DisplayFromStr
where
    T: Display,
{
    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.collect_str(&source)
    }
}

Required Methods

Serialize this value into the given Serde serializer.

Implementations on Foreign Types

Implementors