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

如何在Rust中使用Serde将Map反序列化为枚举的Vector?

解决方案

要实现将YAML中的Map结构反序列化为Vec<Sink>枚举列表,且无需自定义反序列化器,可以通过Serde的#[serde(from)]属性结合From trait转换来完成,步骤如下:

1. 添加依赖

确保Cargo.toml中包含Serde和serde_yaml依赖:

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

2. 定义结构体与枚举

为所有类型派生Deserialize trait,并处理默认值(比如CsvSink的append字段在YAML中未提供的情况):

use serde::Deserialize;
use std::collections::HashMap;

#[derive(Debug, Deserialize)]
pub enum Sink {
    Csv(CsvSink),
    Json(JsonSink),
}

#[derive(Debug, Deserialize)]
pub struct CsvSink {
    file_path: String,
    delimiter: String,
    // 为未在YAML中定义的字段提供默认值
    #[serde(default = "default_append")]
    append: bool,
}

// 默认append为false
fn default_append() -> bool {
    false
}

#[derive(Debug, Deserialize)]
pub struct JsonSink {
    file_path: String,
    another: String,
}

#[derive(Debug, Deserialize)]
pub struct InferenceConfig {
    pub name: String,
    // 告诉Serde先将该字段反序列化为HashMap,再转换为Vec<Sink>
    #[serde(from = "HashMap<String, serde_yaml::Value>")]
    pub output_data_specs: Vec<Sink>,
}

3. 实现From trait完成转换

为Vec<Sink>实现从HashMap<String, serde_yaml::Value>的转换,根据YAML中的键名(csv/json)解析对应的枚举变体:

impl From<HashMap<String, serde_yaml::Value>> for Vec<Sink> {
    fn from(map: HashMap<String, serde_yaml::Value>) -> Self {
        map.into_iter()
            .filter_map(|(key, value)| match key.as_str() {
                "csv" => serde_yaml::from_value(value).ok().map(Sink::Csv),
                "json" => serde_yaml::from_value(value).ok().map(Sink::Json),
                // 忽略未知的接收器类型,也可根据需求返回错误
                _ => None,
            })
            .collect()
    }
}

4. 测试反序列化

编写测试代码验证功能:

fn main() -> Result<(), serde_yaml::Error> {
    let yaml_content = r#"
name: "test_inference"
output_data_specs:
  csv:
    file_path: "/output-data.csv"
    delimiter: ","
  json:
    file_path: "/output/"
    another: "foo"
"#;

    let config: InferenceConfig = serde_yaml::from_str(yaml_content)?;
    println!("{:#?}", config);
    Ok(())
}

关键说明

  • #[serde(from = "...")]属性让Serde自动完成从HashMap到Vec的转换,无需编写自定义反序列化逻辑。
  • 在From trait的实现中,使用serde_yaml::from_value将YAML值解析为对应的结构体,再包装成枚举变体。
  • 对于YAML中未定义的字段(如CsvSink的append),通过#[serde(default)]或自定义默认函数避免反序列化失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 08:32:52