处理一组值而不将它们缓冲到 Vec 中
假设我们有一个整数数组,我们想要计算出最大值,而不是一次性将整个数组保存在内存中。这种方法可以适用于处理在反序列化而不是之后需要处理数据的各种其他情况。
extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
use serde::{de, Deserialize, Deserializer};
use std::cmp;
use std::fmt;
use std::marker::PhantomData;
#[derive(Deserialize)]
struct Outer {
id: String,
// Deserialize this field by computing the maximum value of a sequence
// (JSON array) of values.
#[serde(deserialize_with = "deserialize_max")]
// Despite the struct field being named `max_value`, it is going to come
// from a JSON field called `values`.
#[serde(rename(deserialize = "values"))]
max_value: u64,
}
/// Deserialize the maximum of a sequence of values. The entire sequence
/// is not buffered into memory as it would be if we deserialize to Vec<T>
/// and then compute the maximum later.
///
/// This function is generic over T which can be any type that implements
/// Ord. Above, it is used with T=u64.
fn deserialize_max<T, D>(deserializer: D) -> Result<T, D::Error>
where T: Deserialize + Ord,
D: Deserializer
{
struct MaxVisitor<T>(PhantomData<T>);
impl<T> de::Visitor for MaxVisitor<T>
where T: Deserialize + Ord
{
/// Return type of this visitor. This visitor computes the max of a
/// sequence of values of type T, so the type of the maximum is T.
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a sequence of numbers")
}
fn visit_seq<V>(self, mut visitor: V) -> Result<T, V::Error>
where V: de::SeqVisitor
{
// Start with max equal to the first value in the seq.
let mut max = match visitor.visit()? {
Some(value) => value,
None => {
// Cannot take the maximum of an empty seq.
let msg = "no values in seq when looking for maximum";
return Err(de::Error::custom(msg));
}
};
// Update the max while there are additional values.
while let Some(value) = visitor.visit()? {
max = cmp::max(max, value);
}
Ok(max)
}
}
// Create the visitor and ask the deserializer to drive it. The
// deserializer will call visitor.visit_seq if a seq is present in
// the input data.
let visitor = MaxVisitor(PhantomData);
deserializer.deserialize_seq(visitor)
}
fn main() {
let j = r#"
{
"id": "demo-deserialize-max",
"values": [
256,
100,
384,
314,
271
]
}
"#;
let out: Outer = serde_json::from_str(j).unwrap();
// Prints "max value: 384"
println!("max value: {}", out.max_value);
}