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

Rust:将JSON解析为复杂枚举时如何减少冗余模式匹配代码

问题原因

默认情况下,serde 反序列化枚举类型时,要求 JSON 结构的外层键为枚举的变体名称,例如要解析为 ResponseFromNetwork::FirstPossibleResponse,对应的 JSON 格式应为:

{
  "FirstPossibleResponse": {
    "first_field": "first_value"
  }
}

而你实际收到的 JSON 是结构体的直接内容,没有外层的变体名包裹,因此直接反序列化枚举时会报错,提示找不到匹配的变体。

解决方案

给枚举添加 #[serde(untagged)] 属性即可实现需求,serde 会自动按枚举变体的定义顺序,尝试将 JSON 内容匹配到对应变体的内部结构体,无需手动编写嵌套匹配逻辑。

修改后的完整代码示例

use serde::Deserialize;
use serde_json;

#[derive(Deserialize, Debug)]
struct FirstPossibleResponse {
    first_field: String,
}

#[derive(Deserialize, Debug)]
struct SecondPossibleResponse {
    second_field: String,
}

// 核心修改:添加untagged属性
#[derive(Deserialize, Debug)]
#[serde(untagged)]
enum ResponseFromNetwork {
    FirstPossibleResponse(FirstPossibleResponse),
    SecondPossibleResponse(SecondPossibleResponse),
}

impl From<String> for ResponseFromNetwork {
    fn from(r: String) -> Self {
        // 无需嵌套匹配,直接反序列化即可
        serde_json::from_slice(r.as_bytes())
            .unwrap_or_else(|_| unimplemented!("未匹配到已知的响应格式"))
    }
}

fn main() {
    let data_first = r#"
        {
            "first_field": "first_value"
        }"#;
    let data_second = r#"
        {
            "second_field": "first_value"
        }"#;
        
    print!("{:?}", ResponseFromNetwork::from(data_first.to_owned()));
    print!("{:?}", ResponseFromNetwork::from(data_second.to_owned()));
}

注意事项

  • 如果不同响应结构体的字段存在重叠,需要把匹配规则更严格、优先级更高的变体放在枚举定义的前面,避免serde提前匹配到错误的变体。
  • 新增响应类型时,仅需定义对应的结构体,再往ResponseFromNetwork中添加新变体即可,无需修改解析逻辑,维护成本极低。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 18:36:07