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.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.