C# XML 反序列化

问题描述:

我有一个带有不同类型对象数组的 xml.当 xmlchoiceidentifier 到达关键字结构时,我遇到了问题.当它反序列化时,它只返回 null.

I have xml that is returned with an array of different types of objects. I am having trouble with the xmlchoiceidentifier when it gets to the keyword struct. When it deserializes it, it just returns null.

这是我要反序列化的 xml:

Here is the xml that I am trying to deserialize:

<struct>
   <member>
      <name>result</name>
      <value><boolean>1</boolean></value>
   </member>
   <member>
      <name>user_info</name>
      <value>
         <struct>
            <member>
               <name>First Name</name>
               <value><string>John</string></value>
            </member>
            <member>
               <name>Last Name</name>
               <value><string>Smith</string></value>
            </member>
         </struct>
      </value>
   </member>
</struct>

这是我用于反序列化的代码:

Here is the code I have for deserialization:

public class ResponseStruct
{
    [XmlArray("struct"), XmlArrayItem("member")]
    public List<ResponseMember> Struct { get; set; }
}

public class ResponseArray
{
    [XmlArray("array"), XmlArrayItem("data")]
    public List<ResponseMemberValue> Array { get; set; }
}

public class ResponseMember
{
    [XmlElement("name")]
    public string Name { get; set; }

    [XmlElement("value")]
    public ResponseMemberValue Value { get; set; }
}

public class ResponseMemberValue
{
    [XmlChoiceIdentifier("ValueChoice"), XmlElement("boolean", typeof(bool)), XmlElement("int", typeof(int)), XmlElement("string", typeof(string)), XmlElement("datetime", typeof(DateTime)), XmlElement("double", typeof(double)), XmlElement("base64", typeof(string)), XmlElement("array", typeof(ResponseArray)), XmlElement("struct", typeof(ResponseStruct))]
    public object Value { get; set; }

    [XmlIgnore]
    public virtual ValueType ValueChoice { get; set; }

    public enum ValueType
    {
        @string,
        @int,
        @datetime,
        @double,
        base64,
        array,
        boolean,
        @struct
    }
}

你的主要问题是你已经为 [XmlArray("struct"), XmlArrayItem("member")] 指定了[XmlArray("struct"), XmlArrayItem("member")]>公共列表结构{得到;放;}.这意味着该集合的 XML 应该有一个名为 的外部包装元素.但是,外部 元素由包含的 XmlElement("struct", typeof(ResponseStruct)) 属性指定ResponseMemberValue.Value 属性 - 但您的 XML 只有一层 元素.因此,您需要使用[XmlElement("member")] 指定该集合没有具有外部容器元素.而且,虽然您的 XML 不包含 元素的示例,但我怀疑您也应该对 ResponseArray 做同样的事情.

Your main problem is that you have specified [XmlArray("struct"), XmlArrayItem("member")] for public List<ResponseMember> Struct { get; set; }. This means that the XML for this collection should have an outer wrapper element named <struct>. However, an outer <struct> element is also specified by the XmlElement("struct", typeof(ResponseStruct)) attribute on the containing ResponseMemberValue.Value property - but your XML has only one level of <struct> elements. Thus you need to specify that this collection does not have an outer container element, by using [XmlElement("member")]. And, while your XML does not include a sample of the <array> element, I suspect you should do the same for ResponseArray also.

接下来,您需要使用[XmlRoot][XmlType] 指定根元素名称.如果使用后者,它将自动用作多态 Value 元素中的元素名称.

Next, you need to specify the root element name using [XmlRoot] or [XmlType]. If you use the latter, it will be used automatically as the element name in the polymorphic Value element.

因此:

[XmlType("struct")]
public class ResponseStruct
{
    [XmlElement("member")]
    public List<ResponseMember> Struct { get; set; }
}

[XmlType("array")]
public class ResponseArray
{
    [XmlElement("data")]
    public List<ResponseMemberValue> Array { get; set; }
}

public class ResponseMember
{
    [XmlElement("name")]
    public string Name { get; set; }

    [XmlElement("value")]
    public ResponseMemberValue Value { get; set; }
}

public class ResponseMemberValue
{
    [XmlChoiceIdentifier("ValueChoice")]
    [XmlElement("boolean", typeof(bool)), 
    XmlElement("int", typeof(int)), 
    XmlElement("string", typeof(string)), 
    XmlElement("datetime", typeof(DateTime)), 
    XmlElement("double", typeof(double)), 
    XmlElement("base64", typeof(string)), 
    XmlElement(typeof(ResponseArray)), 
    XmlElement(typeof(ResponseStruct))]
    public object Value { get; set; }

    [XmlIgnore]
    public virtual ValueType ValueChoice { get; set; }

    public enum ValueType
    {
        @string,
        @int,
        @datetime,
        @double,
        base64,
        array,
        boolean,
        @struct
    }
}

原型 fiddle.