pub trait DeserializeSeed<'de>: Sized {
type Value;
// Required method
fn deserialize<D>(
self,
deserializer: D,
) -> Result<Self::Value, <D as Deserializer<'de>>::Error>
where D: Deserializer<'de>;
}
Expand description
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<'de, T: Deserialize<'de>>() -> Result<T, Error>
Adjusting an API like this to support stateful deserialization is a matter of accepting a seed as input:
fn func_seed<'de, T: DeserializeSeed<'de>>(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.
§Lifetime
The 'de
lifetime of this trait is the lifetime of data that may be
borrowed by Self::Value
when deserialized. See the page Understanding
deserializer lifetimes for a more detailed explanation of these lifetimes.
§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.
use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
use std::fmt;
use std::marker::PhantomData;
// 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<'de, 'a, T> DeserializeSeed<'de> for ExtendVec<'a, T>
where
T: Deserialize<'de>,
{
// 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<'de>,
{
// Visitor implementation that will walk an inner array of the JSON
// input.
struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec<T>);
impl<'de, 'a, T> Visitor<'de> for ExtendVecVisitor<'a, T>
where
T: Deserialize<'de>,
{
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "an array of integers")
}
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
where
A: SeqAccess<'de>,
{
// Decrease the number of reallocations if there are many elements
if let Some(size_hint) = seq.size_hint() {
self.0.reserve(size_hint);
}
// Visit each element in the inner array and push it onto
// the existing vector.
while let Some(elem) = seq.next_element()? {
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<'de, T> Visitor<'de> for FlattenedVecVisitor<T>
where
T: Deserialize<'de>,
{
// This Visitor constructs a single Vec<T> to hold the flattened
// contents of the inner arrays.
type Value = Vec<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "an array of arrays")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Vec<T>, A::Error>
where
A: SeqAccess<'de>,
{
// 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(()) = seq.next_element_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)?;
Required Associated Types§
Required Methods§
sourcefn deserialize<D>(
self,
deserializer: D,
) -> Result<Self::Value, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
fn deserialize<D>(
self,
deserializer: D,
) -> Result<Self::Value, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
Equivalent to the more common Deserialize::deserialize
method, except
with some initial piece of data (the seed) passed in.