反序列化对象忽略某些节点

Posted

技术标签:

【中文标题】反序列化对象忽略某些节点【英文标题】:Deserializing object ignoring certain nodes 【发布时间】:2020-09-16 00:55:31 【问题描述】:

我有一个使用 XmlSerializer 序列化的对象。当尝试将此 XML 文件反序列化回对象时,由于某种原因它正在跳过一个节点。

<?xml version="1.0" encoding="utf-8"?>
<Dialogue xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Conversations>
    <Conversation Id="993fed92-6917-4003-975f-78df4ca77257" Name="sdfsf">
      <TextNode Id="8ce1fba9-9daf-4145-b374-d8d7df6ca983" IsGraphEntryPoint="false" NodePositionX="1056" NodePositionY="341">
        <Speaker>None</Speaker>
        <Lines />
      </TextNode>
      <ChoiceNode Id="7c697932-dbde-47a2-b931-bc881811ef63" IsGraphEntryPoint="false" NodePositionX="783" NodePositionY="605">
        <Choices>
          <ChoiceOptionNode ChoiceId="cbe28c44-a535-4191-80b2-1bb3d1881cb7" PortName="Choice#1" ConnectsTo="82fefda3-f6d9-4462-a39e-a20c56f97bcb">
            <Lines>
              <ChoiceOptionLineNode>
                <LanguageId>42d97432-c027-416d-2aa8-1ec47ca1410e</LanguageId>
                <LanguageCode>NL</LanguageCode>
                <Text />
              </ChoiceOptionLineNode>
            </Lines>
          </ChoiceOptionNode>
        </Choices>
      </ChoiceNode>
    </Conversation>
  </Conversations>
</Dialogue>

所有 Textnodes 都正确反序列化,但 Choicenodes 似乎完全被忽略了。

对象本身:

public class ChoiceNode : BaseConversationNode
    
        [XmlArray("Choices")]
        [XmlArrayItem(ElementName = "ChoiceOptionNode")]
        public List<ChoiceOptionNode> Choices;
    

public class ChoiceOptionNode
    
        [XmlAttribute]
        public Guid ChoiceId;
        [XmlAttribute]
        public string PortName;
        [XmlArray("Lines")]
        [XmlArrayItem(ElementName = "ChoiceOptionLineNode")]
        public List<ChoiceOptionLineNode> Lines;
        [XmlAttribute]
        public Guid ConnectsTo;
    

public class ChoiceOptionLineNode
    
        public Guid LanguageId;
        public string LanguageCode;
        public string Text;
    

public abstract class BaseConversationNode
    
        [XmlElement(ElementName = "Connections")]
        public List<Output> Connections = new List<Output>();
        [XmlIgnore]
        public GraphNode Node;
        [XmlAttribute]
        public Guid Id;
        [XmlAttribute]
        public bool IsGraphEntryPoint;
        [XmlIgnore]
        public Rect NodeRect;
        [XmlAttribute]
        public float NodePositionX;
        [XmlAttribute]
        public float NodePositionY;
        /// <summary>
        /// The hex color of the node window
        /// </summary>
        /// <returns></returns>
        [XmlIgnore]
        public string NodeColorHex => !String.IsNullOrEmpty(options?.NodeColor) ? options.NodeColor : "c1c1c1";
        [XmlIgnore]
        public float NodeWidth => options?.NodeWidth ?? 200;
        [XmlIgnore]
        public float NodeHeight => options?.NodeHeight ?? 150;

        [XmlIgnore]
        private NodeOptionsAttribute _options;
        [XmlIgnore]
        private NodeOptionsAttribute options
        
            get
            
                if (_options == null)
                
                    NodeOptionsAttribute attr = (NodeOptionsAttribute)Attribute.GetCustomAttribute(this.GetType(), typeof(NodeOptionsAttribute));
                    _options = attr;
                

                return _options;
            
        
        [XmlIgnore]
        public List<Language> Languages;


[XmlRoot(ElementName = "Connection")]
    public class Output
    
        [XmlAttribute]
        public Guid ConnectsTo;
        [XmlAttribute]
        public string PortName;
        [XmlAttribute]
        public Direction PortDirection;
        [XmlAttribute]
        public Port.Capacity Capacity;
    

 public class Dialogue
    
        /// <summary>
        /// The list of Conversations
        /// </summary>
        [XmlArrayItem(ElementName = "Conversation")]
        public List<Conversation> Conversations;
        /// <summary>
        /// The list of Languages
        /// </summary>
        public List<Language> Languages;

        [XmlIgnore]
        private List<Type> nodeTypes;
        [XmlIgnore]
        public List<Type> NodeTypes
        
            get
            
                if (nodeTypes == null)
                
                    nodeTypes = AppDomain.CurrentDomain.GetAssemblies()
                        .SelectMany(assembly =>
                            assembly.GetTypes())
                            .Where(type =>
                                type.IsSubclassOf(typeof(BaseConversationNode))
                                //&& type.CustomAttributes.Any(x => x.AttributeType != typeof(AutoGeneratedNodeAttribute))
                                && !type.Equals(typeof(StartNode))
                            )
                            .ToList();
                

                return nodeTypes;
            
        
      

public class Language
    
        [XmlAttribute]
        public Guid Id;
        public string Name;
        public string Code;
      

public class Conversation
    
        [XmlAttribute]
        public Guid Id;
        [XmlAttribute]
        public string Name;
        [XmlElement(typeof(StartNode), ElementName = "StartNode")]
        [XmlElement(typeof(TextNode), ElementName = "TextNode")]
        public List<BaseConversationNode> Nodes;

我觉得这很奇怪,因为我使用的 XML 正是 XML 序列化程序首先返回的内容。你会认为它能够正确反序列化它自己的序列化 XML...

我在这里错过了什么?

亲切的问候,

-弗迪

编辑:忘记添加基类。 编辑 2:我是个笨蛋,忘记在第一次编辑时添加其他相关类。

【问题讨论】:

【参考方案1】:

我注意到了我的错误。如下:

[XmlElement(typeof(StartNode), ElementName = "StartNode")]
[XmlElement(typeof(TextNode), ElementName = "TextNode")]
public List<BaseConversationNode> Nodes;

我应该在 Nodes 变量中添加另一个 XmlElement 属性:

[XmlElement(typeof(StartNode), ElementName = "StartNode")]
[XmlElement(typeof(TextNode), ElementName = "TextNode")]
[XmlElement(typeof(ChoiceNode), ElementName = "ChoiceNode")]
public List<BaseConversationNode> Nodes;

这确实可以正确地反序列化 XML。

【讨论】:

以上是关于反序列化对象忽略某些节点的主要内容,如果未能解决你的问题,请参考以下文章

C# 在忽略命名空间的同时反序列化 xml

如何反序列化 JSON 数组并忽略根节点?

如何在没有jackson注释的情况下忽略反序列化的某些字段?

Gson 在反序列化对象时忽略 null

在反序列化时如何忽略JSON对象数组中的空白数组?

SharpSerializer:从反序列化中忽略属性/属性