使用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不允许对象存在重复键,因此触发报错。
具体修复方案
- 仅在枚举类型上使用
#[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, }
- 若结构体也需输出类型标识,改用自定义字段名,避免与枚举的
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
相关产品推荐
相关产品推荐

