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

如何用Serde将含Vec字段的Rust结构体展开为多条记录?

解决方案:将Rust结构体展开为多条序列化记录

Serde本身没有提供直接生成多条序列化记录的机制,因为它的设计是将单个值转换为序列化格式。针对你的需求,这里提供两种可行方案:

一、手动转换方案(快速解决简单场景)

如果你的结构体结构固定,直接手动将原结构体转换为多条目标记录的集合,再序列化这个集合即可。这种方式直观易懂,适合入门:

use serde::Serialize;
use std::io;

#[derive(Serialize)]
struct Test {
    a: i32,
    b: Vec<i32>,
}

#[derive(Serialize)]
struct ExplodedTest {
    a: i32,
    b: i32,
}

fn main() -> Result<(), io::Error> {
    let test_struct = Test {
        a: 5,
        b: vec![1, 2, 3, 4],
    };

    // 将原结构体转换为多条展开后的记录
    let exploded_records: Vec<ExplodedTest> = test_struct
        .b
        .into_iter()
        .map(|b_val| ExplodedTest {
            a: test_struct.a,
            b: b_val,
        })
        .collect();

    let writer = io::BufWriter::new(std::fs::File::create("test.json")?);
    // 序列化记录集合,生成JSON数组
    serde_json::to_writer_pretty(writer, &exploded_records)?;

    Ok(())
}

运行后,test.json会生成包含4条记录的JSON数组,每条记录对应你需要的{"a":5,"b":1}格式。

二、通用递归展开方案(支持复杂嵌套结构)

如果你的实际场景存在多层嵌套的结构体,且需要自动展开所有Vec类型字段(包括嵌套字段),可以借助serde_json::Value作为中间层,通过递归遍历实现通用展开:

use serde::Serialize;
use serde_json::{json, Value};
use std::io;

// 示例嵌套结构体
#[derive(Serialize)]
struct Test {
    a: i32,
    b: Vec<i32>,
    c: NestedStruct,
}

#[derive(Serialize)]
struct NestedStruct {
    d: String,
    e: Vec<f64>,
}

// 递归展开所有Vec字段的核心函数
fn explode_value(value: Value) -> Vec<Value> {
    match value {
        Value::Object(obj) => {
            // 找到第一个Vec类型的字段(若有多个,会递归处理所有组合)
            if let Some((key, Value::Array(arr))) = obj.iter().find(|(_, v)| v.is_array()) {
                let key = key.clone();
                // 保留当前对象中除Vec字段外的所有内容
                let mut base_obj = obj.clone();
                base_obj.remove(&key);

                arr.into_iter()
                    .flat_map(|item| {
                        let mut new_obj = base_obj.clone();
                        new_obj.insert(key.clone(), item);
                        // 递归处理新对象中的嵌套Vec字段
                        explode_value(Value::Object(new_obj))
                    })
                    .collect()
            } else {
                // 没有Vec字段,直接返回单条记录
                vec![Value::Object(obj)]
            }
        }
        // 非对象类型直接返回单条记录
        _ => vec![value],
    }
}

fn main() -> Result<(), io::Error> {
    let test_struct = Test {
        a: 5,
        b: vec![1, 2],
        c: NestedStruct {
            d: "hello".to_string(),
            e: vec![3.14, 2.71],
        },
    };

    // 先将原结构体序列化为Value
    let value = serde_json::to_value(&test_struct)?;
    // 递归展开所有Vec字段
    let exploded_values = explode_value(value);

    let writer = io::BufWriter::new(std::fs::File::create("test.json")?);
    serde_json::to_writer_pretty(writer, &exploded_values)?;

    Ok(())
}

这个方案会自动处理所有嵌套的Vec字段,生成所有可能的组合记录。比如上面的示例会生成4条记录,每条包含a、d,以及b和e的一组值。

补充说明

你尝试的serde_query主要用于反序列化时从复杂数据中提取指定字段,并不适用于序列化阶段的记录展开,所以无法满足需求。自定义序列化器虽然可行,但实现复杂度高,不如上述两种方案灵活高效。

内容的提问来源于stack exchange,提问作者charles monod-broca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 11:12:35