You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中使用serde无中间结构实现记录转列式反序列化的方法

实现方案

serde 完全支持跳过中间结构直接完成目标格式反序列化,通过手动实现Deserialize trait 即可满足需求,具体实现如下:


依赖配置

首先在Cargo.toml中引入必要依赖:

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

核心代码实现

use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
use serde_json::Value;
use std::fmt;

// 目标结构体,Rust约定结构体使用大驼峰命名
#[derive(Debug, PartialEq)]
struct Data {
    key1: Vec<i8>,
    key2: Vec<i8>,
}

impl<'de> Deserialize<'de> for Data {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct DataVisitor;

        impl<'de> Visitor<'de> for DataVisitor {
            type Value = Data;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("array of objects or 2D array of i8")
            }

            // 处理外层数组,两种输入的外层均为数组结构
            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
            where
                A: SeqAccess<'de>,
            {
                // 直接初始化目标字段的Vec,不需要中间存储
                let mut key1 = Vec::new();
                let mut key2 = Vec::new();

                while let Some(element) = seq.next_element::<Value>()? {
                    match element {
                        // 兼容第一种输入:数组元素为JSON对象
                        Value::Object(mut map) => {
                            let k1 = map
                                .get("key1")
                                .and_then(|v| v.as_i64())
                                .ok_or_else(|| serde::de::Error::custom("missing or invalid key1"))?
                                as i8;
                            let k2 = map
                                .get("key2")
                                .and_then(|v| v.as_i64())
                                .ok_or_else(|| serde::de::Error::custom("missing or invalid key2"))?
                                as i8;
                            key1.push(k1);
                            key2.push(k2);
                        }
                        // 兼容第二种输入:数组元素为嵌套数组
                        Value::Array(mut arr) => {
                            if arr.len() != 2 {
                                return Err(serde::de::Error::custom(
                                    "inner array must have exactly 2 elements",
                                ));
                            }
                            let k1 = arr
                                .remove(0)
                                .as_i64()
                                .ok_or_else(|| serde::de::Error::custom("invalid first element"))?
                                as i8;
                            let k2 = arr
                                .remove(0)
                                .as_i64()
                                .ok_or_else(|| serde::de::Error::custom("invalid second element"))?
                                as i8;
                            key1.push(k1);
                            key2.push(k2);
                        }
                        _ => return Err(serde::de::Error::custom("invalid element type")),
                    }
                }

                Ok(Data { key1, key2 })
            }
        }

        deserializer.deserialize_seq(DataVisitor)
    }
}

// 测试代码
fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 测试第一种输入:对象数组(如果你的原始输入没有外层[],手动拼接即可转为合法JSON)
    let obj_input = r#"[
        {"key1": 40, "key2": 50},
        {"key1": 41, "key2": 51}
    ]"#;
    let data1: Data = serde_json::from_str(obj_input)?;
    assert_eq!(data1.key1, vec![40, 41]);
    assert_eq!(data1.key2, vec![50, 51]);

    // 测试第二种输入:嵌套数组
    let arr_input = r#"[[40,50],[41,51]]"#;
    let data2: Data = serde_json::from_str(arr_input)?;
    assert_eq!(data2.key1, vec![40, 41]);
    assert_eq!(data2.key2, vec![50, 51]);

    println!("两种格式反序列化均验证通过");
    Ok(())
}

实现说明

  • 全程没有创建中间结构体、中间Vec<Vec<i8>>等临时对象,反序列化过程中直接将对应值写入目标结构体的Vec字段,性能开销更低
  • 自动兼容两种输入格式,不需要额外的格式判断逻辑
  • 可以根据业务需求扩展错误处理逻辑,处理字段缺失、类型不匹配等异常场景
  • 如果第一种原始输入是无外层数组包裹的裸对象序列,只需在输入字符串首尾拼接[和]转换为合法JSON数组后再调用反序列化方法即可

内容的提问来源于stack exchange,提问作者mbfernan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 04:30:02