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

使用Serde序列化枚举时为何出现重复type字段?

问题描述

我编写了如下Rust代码:

let vid = VideoLayer::VideoConcatLayer(VideoConcatLayer {
    list: vec![VideoLayer::VideoAssetLayer(VideoAssetLayer {
        asset: T3Val::Ready(
            Ready {
                val: "hello".to_string()
            })
        })]
    });

其中VideoLayer和T3Val为枚举类型,VideoConcatLayer、VideoAssetLayer和Ready为结构体。使用Serde进行序列化时,出现"type"字段重复的问题并触发报错,序列化结果如下:

{"type":"VideoConcatLayer","type":"VideoConcatLayer","list":[{"type":"VideoAssetLayer","type":"VideoAssetLayer","asset":{"type":"Ready","type":"Ready","val":"hello"}}]}
解决方法

这个问题的核心是枚举与其内部包裹的结构体同时配置了Serde的type类型标签,导致序列化时双方都输出了type字段,而JSON不允许对象存在重复键,因此触发报错。

具体修复方案

  1. 仅在枚举类型上使用#[serde(tag = "type")],移除结构体上的同标签配置:
#[derive(Serialize, Deserialize)]
#[serde(tag = "type")] // 仅枚举添加type标签
enum VideoLayer {
    VideoConcatLayer(VideoConcatLayer),
    VideoAssetLayer(VideoAssetLayer),
}

#[derive(Serialize, Deserialize)]
struct VideoConcatLayer { // 结构体无需type标签
    list: Vec<VideoLayer>,
}

#[derive(Serialize, Deserialize)]
struct VideoAssetLayer { // 结构体无需type标签
    asset: T3Val,
}

#[derive(Serialize, Deserialize)]
#[serde(tag = "type")] // 枚举添加type标签
enum T3Val {
    Ready(Ready),
}

#[derive(Serialize, Deserialize)]
struct Ready { // 结构体无需type标签
    val: String,
}
  1. 若结构体也需输出类型标识,改用自定义字段名,避免与枚举的type标签冲突:
#[derive(Serialize, Deserialize)]
struct VideoConcatLayer {
    #[serde(rename = "struct_type")]
    type_name: &'static str, // 手动定义结构体专属类型字段
    list: Vec<VideoLayer>,
}

原理说明

Serde的#[serde(tag = "type")]会自动为枚举的每个变体生成type字段,用于标识枚举类型。如果内部结构体也配置了相同标签或自定义了type字段,就会导致JSON对象出现重复键,进而触发序列化错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:40:33