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

如何利用多态反序列化两种仅消息值类型不同的XML?数据结构设计及问题解决

解决相似结构XML的反序列化问题:基于抽象类的多类型消息处理

问题背景

我最近在处理两种结构几乎完全一致的XML,唯一区别是消息节点里的MessageValue_Type_X字段类型不同(一个是数值型,一个是字符串型)。XML示例如下:

<DOCUMENTS>
  <DOCUMENT>
    <DOC_NAME>1</DOC_NAME>
    <messages>
      <message>
        <ID>1</ID>
        <MessageValue_Type_1>22222</MessageValue_Type_1>
      </message>
      <message>
        <ID>2</ID>
        <MessageValue_Type_1>3333</MessageValue_Type_1>
      </message>
    </messages>
  </DOCUMENT>
  <DOCUMENT>
    <DOC_NAME>3</DOC_NAME>
    <messages>
      <message>
        <ID>1</ID>
        <MessageValue_Type_2>AAAAAAA</MessageValue_Type_2>
      </message>
      <message>
        <ID>2</ID>
        <MessageValue_Type_2>BBBBB</MessageValue_Type_2>
      </message>
    </messages>
  </DOCUMENT>
</DOCUMENTS>

我的目标是用Type_1_Document和Type_2_Document分别反序列化对应的<DOCUMENT>节点,最初设计了基于抽象类的结构,但一直无法完成反序列化,后来调整XML特性配置后解决了问题。

最初的尝试代码

一开始的代码结构试图用抽象基类+子类重写属性的方式实现,但因XML特性配置错误导致反序列化失败:

[XmlRoot("DOCUMENT")]
public abstract class Document
{
    [XmlElement("DOC_NAME")]
    public string DocName { get; set; }
    [XmlIgnore]
    public virtual List<GeneralMessage> messages { get; set; }
}

public class Type_1_Document : Document
{
    [XmlElement("messages")]
    public new List<Message_Type_1> messages { get; set; }
}

public class Type_2_Document : Document
{
    [XmlElement("messages")]
    public new List<Message_Type_2> messages { get; set; }
}

[XmlRoot("message")]
public abstract class GeneralMessage
{
    [XmlElement("ID")]
    public int ID { get; set; }
}

[XmlRoot("message")]
public class Message_Type_1 : GeneralMessage
{
    [XmlElement("MessageValue_Type_1")]
    public int valueType_1 { get; set; }
}

[XmlRoot("message")]
public class Message_Type_2 : GeneralMessage
{
    [XmlElement("MessageValue_Type_2")]
    public int valueType_2 { get; set; }
}

问题解决后的正确配置

经过调整,我找到了两个关键修改点,现在可以正常完成反序列化:

  1. 移除抽象基类上的[XmlRoot]特性:Document和GeneralMessage是抽象基类,不需要标记[XmlRoot],这个特性应该只作用于实际作为序列化根节点的子类(比如Type_1_Document)。
  2. 优化属性的XML特性配置:基类Document的messages用[XmlIgnore]+virtual修饰,子类用new关键字重新定义属性并标记[XmlElement("messages")],确保序列化器能正确识别子类的消息列表类型。

调整后的完整代码:

public abstract class Document
{
    [XmlElement("DOC_NAME")]
    public string DocName { get; set; }
    
    [XmlIgnore]
    public virtual List<GeneralMessage> Messages { get; set; }
}

[XmlRoot("DOCUMENT")]
public class Type_1_Document : Document
{
    [XmlElement("messages")]
    public new List<Message_Type_1> Messages { get; set; }
}

[XmlRoot("DOCUMENT")]
public class Type_2_Document : Document
{
    [XmlElement("messages")]
    public new List<Message_Type_2> Messages { get; set; }
}

public abstract class GeneralMessage
{
    [XmlElement("ID")]
    public int ID { get; set; }
}

public class Message_Type_1 : GeneralMessage
{
    [XmlElement("MessageValue_Type_1")]
    public int ValueType1 { get; set; }
}

public class Message_Type_2 : GeneralMessage
{
    [XmlElement("MessageValue_Type_2")]
    public string ValueType2 { get; set; }
}

现在可以正常使用XmlSerializer完成反序列化:

// 反序列化Type_1类型的XML
XmlSerializer xmls1 = new XmlSerializer(typeof(Type_1_Document));
var result1 = xmls1.Deserialize(new StringReader(type1XmlText));

// 反序列化Type_2类型的XML
XmlSerializer xmls2 = new XmlSerializer(typeof(Type_2_Document));
var result2 = xmls2.Deserialize(new StringReader(type2XmlText));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 23:33:14