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

Serde无法识别未标记枚举变体:data did not match any variant错误排查

Serde未标记枚举反序列化错误排查

问题场景

尝试用Serde解析如下JSON数据:

{
  "data_type": "uint8",
  "scales": [{
    "encoding": "jpeg",
    "key": "4.0x4.0x33.0"
  }]
}

反序列化为以下Rust类型:

#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct DatasetAttributes {
    data_type: String,
    scales: Vec<ScaleEntry>,
}

#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct ScaleEntry {
    pub encoding: CompressionType,
    pub key: String,
}

#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
#[serde(rename_all = "lowercase")]
#[serde(untagged)]
pub enum CompressionType {
    Raw(RawCompression),
    Jpeg(JpegCompression),
}

#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
#[serde(rename_all = "lowercase")]
pub struct JpegCompression {
    quality: i32,
}

#[derive(Clone, Serialize, Deserialize, PartialEq, Debug, Default)]
pub struct RawCompression;

执行时触发错误:

Error: data did not match any variant of untagged enum CompressionType

疑问:是否误解了Serde未标记枚举的处理逻辑?还是代码存在问题?

问题原因

核心问题是未标记枚举的结构与JSON数据格式不匹配:

当前CompressionType是未标记枚举,Serde会尝试将encoding字段的内容直接匹配枚举变体的结构。但JSON中encoding是单纯的字符串"jpeg",而你的Jpeg变体对应包含quality字段的JpegCompression结构体,Raw变体对应空结构体RawCompression——两者都无法匹配单纯的字符串值,因此触发错误。

解决方法

根据你的需求,可以选择以下三种方案之一:

方案1:简化枚举,直接匹配字符串

如果JpegCompression和RawCompression不需要存储额外参数,直接将枚举变体改为对应字符串:

#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
#[serde(rename_all = "lowercase")]
pub enum CompressionType {
    Raw,
    Jpeg,
}

此时JSON中的"jpeg"会直接匹配CompressionType::Jpeg,"raw"匹配CompressionType::Raw,无需额外结构体。

方案2:调整JSON结构,适配嵌套对象

如果需要保留结构体存储额外参数(比如quality),需将JSON的encoding字段改为嵌套对象:

{
  "data_type": "uint8",
  "scales": [{
    "encoding": {
      "jpeg": { "quality": 90 }
    },
    "key": "4.0x4.0x33.0"
  }]
}

未标记枚举会自动识别嵌套的对象结构,匹配对应的变体和结构体参数。

方案3:自定义反序列化逻辑

如果无法修改现有JSON格式,需给CompressionType实现自定义反序列化,手动将字符串映射到对应变体:

use serde::{Deserialize, Deserializer};

#[derive(Clone, Serialize, PartialEq, Debug)]
#[serde(rename_all = "lowercase")]
pub enum CompressionType {
    Raw(RawCompression),
    Jpeg(JpegCompression),
}

#[derive(Clone, Serialize, PartialEq, Debug, Default)]
pub struct RawCompression;

#[derive(Clone, Serialize, PartialEq, Debug)]
#[serde(rename_all = "lowercase")]
pub struct JpegCompression {
    quality: i32,
}

impl<'de> Deserialize<'de> for CompressionType {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        match s.as_str() {
            "raw" => Ok(CompressionType::Raw(RawCompression)),
            "jpeg" => Ok(CompressionType::Jpeg(JpegCompression { quality: 80 })), // 可根据需求设置默认值或调整逻辑
            other => Err(serde::de::Error::unknown_variant(other, &["raw", "jpeg"])),
        }
    }
}

这种方式兼容原有JSON格式,同时保留结构体的扩展能力。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 21:55:00