问题
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.
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
}
}
回答1:
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.
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.
Thus:
[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
}
}
Prototype fiddle.
来源:https://stackoverflow.com/questions/37229202/c-sharp-xml-deserialization