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

如何用Rust的serde和csv crate实现嵌套JSON转带前缀的CSV?

解决方案

要实现嵌套结构体序列化CSV时自动扁平化并添加前缀,最便捷的方式是借助serde_with第三方 crate,无需手动实现完整序列化器。

方法一:使用serde_with的FlattenPrefix

  1. 首先在Cargo.toml中添加依赖:
[dependencies]
serde = { version = "1.0", features = ["derive"] }
csv = "1.2"
serde_with = "3.0"
  1. 修改结构体定义,通过serde_as和FlattenPrefix属性实现带前缀的扁平化:
use serde::Serialize;
use serde_with::{serde_as, FlattenPrefix};

#[serde_as]
#[derive(Serialize)]
struct Foo {
    // 给Bar的所有字段添加"bar_"前缀并扁平化
    #[serde_as(as = "FlattenPrefix<'bar_>")]
    bar: Bar,
}

#[derive(Serialize)]
struct Bar {
    baz: String,
    qux: String,
}
  1. 序列化到CSV的示例代码:
use csv::Writer;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let foo = Foo {
        bar: Bar {
            baz: "test_baz".to_string(),
            qux: "test_qux".to_string(),
        },
    };

    let mut writer = Writer::from_writer(std::io::stdout());
    writer.serialize(foo)?;
    writer.flush()?;

    Ok(())
}

执行后输出的CSV表头为bar_baz,bar_qux,字段值也会对应填充,完全符合需求。这种方式不会影响原结构体的反序列化逻辑,适合大型JSON解析流程。

方法二:手动定义CSV专用结构体(无额外依赖)

如果不想引入第三方 crate,可以专门定义用于CSV序列化的结构体,将嵌套字段展开,再实现原结构体到该结构体的转换:

use serde::Serialize;

// 原结构体,保持原有反序列化逻辑
struct Foo {
    bar: Bar,
}

struct Bar {
    baz: String,
    qux: String,
}

// 用于CSV序列化的扁平化结构体
#[derive(Serialize)]
struct FooCsv {
    bar_baz: String,
    bar_qux: String,
}

// 实现从Foo到FooCsv的转换
impl From<Foo> for FooCsv {
    fn from(foo: Foo) -> Self {
        FooCsv {
            bar_baz: foo.bar.baz,
            bar_qux: foo.bar.qux,
        }
    }
}

序列化时只需将Foo实例转换为FooCsv再传入CSV writer即可。这种方式适合结构体数量较少的场景,但需要维护额外的转换逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:17:29