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

在Rust中无需自定义反序列化器反序列化含单元/非单元的枚举

解决方案

要让Animal::Cat变体同时兼容JSON字符串"Cat"(对应Cat(None))和JSON对象{"Cat": "cat_name"}(对应Cat(Some("cat_name"))),可以通过定义辅助枚举+轻量反序列化辅助函数实现,无需编写整个枚举的自定义反序列化器,具体代码如下:

use serde::{Deserialize, Deserializer, Serialize};

// 辅助枚举:兼容两种JSON格式的Cat值
#[derive(Deserialize)]
#[serde(untagged)]
enum CatValue {
    Unit,
    Name(String),
}

// 将辅助枚举转换为业务需要的Option<String>
fn cat_from_value<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
    D: Deserializer<'de>,
{
    let value = CatValue::deserialize(deserializer)?;
    Ok(match value {
        CatValue::Unit => None,
        CatValue::Name(name) => Some(name),
    })
}

#[derive(Serialize, Deserialize, Debug)]
enum Animal {
    // 为Cat变体指定自定义反序列化逻辑
    #[serde(deserialize_with = "cat_from_value")]
    Cat(Option<String>),
    Dog(String),
    Bird,
}

fn main() {
    let json_animals = r#"
        [
            {"Cat": "Meow"},
            "Cat",
            {"Dog": "Bark"},
            "Bird"
        ]"#;
    println!("{:?}", serde_json::from_str::<Vec<Animal>>(json_animals).unwrap());
}

关键说明

  • CatValue是无标签枚举,会自动匹配两种JSON格式:遇到字符串"Cat"时解析为CatValue::Unit,遇到对象{"Cat": "..."}时解析为CatValue::Name(...)。
  • cat_from_value函数完成格式到业务类型的转换,把辅助枚举映射为Option<String>。
  • 仅为Cat变体指定反序列化逻辑,其他变体保持默认行为,改动最小。

运行代码会输出:

[Cat(Some("Meow")), Cat(None), Dog("Bark"), Bird]

如果不想额外定义辅助枚举,也可以直接处理原始JSON值(可读性稍差):

use serde::{Deserialize, Deserializer, Serialize};
use serde_json::Value;

fn cat_from_value<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
    D: Deserializer<'de>,
{
    let value = Value::deserialize(deserializer)?;
    match value {
        Value::String(s) if s == "Cat" => Ok(None),
        Value::Object(mut obj) => {
            obj.remove("Cat")
                .map(|v| v.as_str().map(|s| s.to_string()).ok_or_else(|| {
                    serde::de::Error::custom("Cat value must be a string")
                }))
                .unwrap_or_else(|| Ok(None))
        }
        _ => Err(serde::de::Error::custom("invalid format for Cat variant")),
    }
}

// Animal枚举和main函数同上述代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 19:10:27