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

quickxml+serde序列化正常但无法反序列化多类型XML元素问题

解决quickxml+serde反序列化Eclipse启动配置XML时属性为空的问题

问题分析

你的代码能正常序列化生成符合结构的XML,但反序列化时attrs字段为空,核心原因有两个:

  • 根节点名称不匹配:结构体EclipseLaunchConfiguration默认序列化的根节点是<EclipseLaunchConfiguration>,但实际Eclipse XML根节点是<launchConfiguration>,导致反序列化上下文不匹配。
  • 未指定子元素映射规则:serde默认不会自动将根节点下的直接子元素(booleanAttribute/stringAttribute等)绑定到attrs字段,需要明确告诉quickxml如何捕获这些子元素。

解决方案

修改代码中的两处关键配置:

1. 修正根节点名称映射

给EclipseLaunchConfiguration结构体添加#[serde(rename = "launchConfiguration")]注解,让序列化/反序列化的根节点与实际XML一致。

2. 绑定子元素到attrs字段

给attrs字段添加#[serde(rename = "$value")]注解,该标记在quickxml的serde实现中代表当前元素的所有子内容(包括子元素),这样所有booleanAttribute/stringAttribute等子元素都会被反序列化为Vec<ConfigAttribute>。

修改后的完整代码

use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename = "launchConfiguration")] // 匹配实际XML根节点名称
struct EclipseLaunchConfiguration {
    #[serde(rename = "@type")]
    configuration_type: String,
    #[serde(rename = "$value")] // 将根节点下的所有子元素映射到attrs
    #[serde(default)]
    attrs: Vec<ConfigAttribute>,
}

#[derive(Debug, Serialize, Deserialize)]
enum ConfigAttribute {
    #[serde(rename = "booleanAttribute")]
    Bool {
        #[serde(rename = "@key")]
        key: String,
        #[serde(rename = "@value")]
        value: bool,
    },
    #[serde(rename = "stringAttribute")]
    Str {
        #[serde(rename = "@key")]
        key: String,
        #[serde(rename = "@value")]
        value: String,
    },
    #[serde(rename = "listAttribute")]
    List{
        #[serde(rename = "@key")]
        key: String,
        #[serde(rename = "listEntry")]
        list_entry: Vec<ListEntry>,
    },
    #[serde(rename = "mapAttribute")]
    Map{
        #[serde(rename = "@key")]
        key: String,
        #[serde(rename = "listEntry")] // 若实际Eclipse用mapEntry则改为mapEntry
        map_entry: Vec<MapEntry>,
    },
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
struct ListEntry {
    #[serde(rename = "@value")]
    value: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
struct MapEntry {
    #[serde(rename = "@key")]
    key: String,
    #[serde(rename = "@value")]
    value: String,
}

#[cfg(test)] mod tests {
    use super::*;

    #[test]
    fn test_to_xml() -> anyhow::Result<()> {
        let config = EclipseLaunchConfiguration {
            configuration_type: "whatever".to_string(),
            attrs: vec![
                ConfigAttribute::Bool{
                    key: "ok".to_string(),
                    value: true,
                },
                ConfigAttribute::Str {
                    key: "hello".to_string(),
                    value: "world".to_string(),
                },
                ConfigAttribute::List{
                    key: "list".to_string(),
                    list_entry: vec![
                        ListEntry {
                            value: "one".to_string(),
                        },
                        ListEntry {
                            value: "two".to_string(),
                        },
                    ],
                },
                ConfigAttribute::Map {
                    key: "map".to_string(),
                    map_entry: vec![
                        MapEntry {
                            key: "one".to_string(),
                            value: "1".to_string(),
                        },
                        MapEntry {
                            key: "two".to_string(),
                            value: "2".to_string(),
                        },
                    ],
                }
            ],
        };
        let xml = quick_xml::se::to_string(&config)?;
        println!("{}", xml);
        let config2: EclipseLaunchConfiguration = quick_xml::de::from_str(&xml)?;
        println!("{:#?}", config2);
        // 验证反序列化结果与原数据一致
        assert_eq!(config.attrs.len(), config2.attrs.len());
        Ok(())
    }
}

验证结果

修改后运行测试,反序列化得到的config2.attrs会包含所有属性元素,长度与原数据一致,且每个元素的内容正确匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 08:27:13