不 buffer 到 Vec 中来处理数组中的值

假设我们有一个整数数组,我们想计算出最大值,而不同时将整个数组保存在内存中。这种方法也可以处理各种其他情况,需要在反序列化的同时处理数据,而不是之后再处理数据。

use serde::{Deserialize, Deserializer};
use serde::de::{self, Visitor, SeqAccess};

use std::{cmp, fmt};
use std::marker::PhantomData;

#[derive(Deserialize)]
struct Outer {
    #[allow(dead_code)]
    id: String,

    // 通过计算序列(JSON 数组)中值的最大值来反序列化此字段。
    #[serde(deserialize_with = "deserialize_max")]
    // 尽管结构体字段被命名为 `max_value`,但实际将来自名为 `values` 的 JSON 字段。
    #[serde(rename(deserialize = "values"))]
    max_value: u64,
}

/// 反序列化值序列的最大值。整个序列不会像如果我们反序列化为 Vec<T> 然后稍后计算最大值那样缓冲到内存中。
///
/// 这个函数是泛型的,T 可以是任何实现 Ord 的类型。上面,它被用于 T=u64。
fn deserialize_max<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
    T: Deserialize<'de> + Ord,
    D: Deserializer<'de>,
{
    struct MaxVisitor<T>(PhantomData<fn() -> T>);

    impl<'de, T> Visitor<'de> for MaxVisitor<T>
    where
        T: Deserialize<'de> + Ord,
    {
        /// 该访问者的返回类型。该访问者计算类型 T 的值序列的最大值,因此最大值的类型为 T。
        type Value = T;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            formatter.write_str("一组非空数字序列")
        }

        fn visit_seq<S>(self, mut seq: S) -> Result<T, S::Error>
        where
            S: SeqAccess<'de>,
        {
            // 从序列中的第一个值开始设置最大值。
            let mut max = seq.next_element()?.ok_or_else(||
                // 在查找最大值时,无法取空序列的最大值。
                de::Error::custom("在查找最大值时序列中没有值")
            )?;

            // 在还有其他值时更新最大值。
            while let Some(value) = seq.next_element()? {
                max = cmp::max(max, value);
            }

            Ok(max)
        }
    }

    // 创建访问者并要求反序列化器驱动它。如果输入数据中存在序列,反序列化器将调用 visitor.visit_seq()。
    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();

    // 打印 "最大值:384"
    println!("最大值:{}", out.max_value);
}