Trait serde::de::DeserializeSeed [] [src]

pub trait DeserializeSeed: Sized {
    type Value;
    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer
; }

DeserializeSeed is the stateful form of the Deserialize trait. If you ever find yourself looking for a way to pass data into a Deserialize impl, this trait is the way to do it.

As one example of stateful deserialization consider deserializing a JSON array into an existing buffer. Using the Deserialize trait we could deserialize a JSON array into a Vec<T> but it would be a freshly allocated Vec<T>; there is no way for Deserialize to reuse a previously allocated buffer. Using DeserializeSeed instead makes this possible as in the example code below.

The canonical API for stateless deserialization looks like this:

fn func<T: Deserialize>() -> Result<T, Error>

Adjusting an API like this to support stateful deserialization is a matter of accepting a seed as input:

fn func_seed<T: DeserializeSeed>(seed: T) -> Result<T::Value, Error>

In practice the majority of deserialization is stateless. An API expecting a seed can be appeased by passing std::marker::PhantomData as a seed in the case of stateless deserialization.

Example

Suppose we have JSON that looks like [[1, 2], [3, 4, 5], [6]] and we need to deserialize it into a flat representation like vec![1, 2, 3, 4, 5, 6]. Allocating a brand new Vec<T> for each subarray would be slow. Instead we would like to allocate a single Vec<T> and then deserialize each subarray into it. This requires stateful deserialization using the DeserializeSeed trait.

// A DeserializeSeed implementation that uses stateful deserialization to
// append array elements onto the end of an existing vector. The preexisting
// state ("seed") in this case is the Vec<T>. The `deserialize` method of
// `ExtendVec` will be traversing the inner arrays of the JSON input and
// appending each integer into the existing Vec.
struct ExtendVec<'a, T: 'a>(&'a mut Vec<T>);

impl<'a, T> DeserializeSeed for ExtendVec<'a, T>
    where T: Deserialize
{
    // The return type of the `deserialize` method. This implementation
    // appends onto an existing vector but does not create any new data
    // structure, so the return type is ().
    type Value = ();

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
        where D: Deserializer
    {
        // Visitor implementation that will walk an inner array of the JSON
        // input.
        struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec<T>);

        impl<'a, T> Visitor for ExtendVecVisitor<'a, T>
            where T: Deserialize
        {
            type Value = ();

            fn visit_seq<V>(self, mut visitor: V) -> Result<(), V::Error>
                where V: SeqVisitor
            {
                // Visit each element in the inner array and push it onto
                // the existing vector.
                while let Some(elem) = visitor.visit()? {
                    self.0.push(elem);
                }
                Ok(())
            }
        }

        deserializer.deserialize_seq(ExtendVecVisitor(self.0))
    }
}

// Visitor implementation that will walk the outer array of the JSON input.
struct FlattenedVecVisitor<T>(PhantomData<T>);

impl<T> Visitor for FlattenedVecVisitor<T>
    where T: Deserialize
{
    // This Visitor constructs a single Vec<T> to hold the flattened
    // contents of the inner arrays.
    type Value = Vec<T>;

    fn visit_seq<V>(self, mut visitor: V) -> Result<Vec<T>, V::Error>
        where V: SeqVisitor
    {
        // Create a single Vec to hold the flattened contents.
        let mut vec = Vec::new();

        // Each iteration through this loop is one inner array.
        while let Some(()) = visitor.visit_seed(ExtendVec(&mut vec))? {
            // Nothing to do; inner array has been appended into `vec`.
        }

        // Return the finished vec.
        Ok(vec)
    }
}

let visitor = FlattenedVecVisitor(PhantomData);
let flattened: Vec<u64> = deserializer.deserialize_seq(visitor)?;

Associated Types

The type produced by using this seed.

Required Methods

Equivalent to the more common Deserialize::deserialize method, except with some initial piece of data (the seed) passed in.

Implementations on Foreign Types

impl<T> DeserializeSeed for PhantomData<T> where
    T: Deserialize
[src]

[src]

Implementors