简体   繁体   English

在C#中使用属性反序列化XML

[英]Deserialize XML with Attributes in C#

I'm having trouble deserializing an XML response from an API call. 我无法从API调用反序列化XML响应。 My 'Option' object's property 'Description' is null. 我的'Option'对象的属性'Description'为null。

Below is a sample of the XML: 以下是XML示例:

<vehicle found="1">
   <description>VehicleDescText</description>
   <buildDate>2000-11-20</buildDate>
   <modelYear>2001</modelYear>
   <optionList>
      <option code="UH8">OptionDesc1</option>
      <option code="UH8">OptionDesc2</option>
   </optionList>
</vehicle>

Here is a sample of C# classes: 以下是C#类的示例:

[DataContract]
[XmlRoot("vehicle")]
public class Vehicle
{
    [DataMember]
    [XmlAttribute("found")]
    public bool Found { get; set; }

    [DataMember]
    [XmlElement("description")]
    public string Description { get; set; }

    [DataMember]
    [XmlElement("buildDate")]
    public string BuildDate { get; set; }

    [DataMember]
    [XmlElement("modelYear")]
    public string ModelYear { get; set; }

    [DataMember]
    [XmlElement("optionList")]
    public List<Option> OptionList { get; set; }
}

public class Option
{
    [DataMember]
    [XmlAttribute("code")]
    public string Code { get; set; }

    [DataMember]
    [XmlElement("option")]
    public string Description { get; set; }
}

Deserializing the object looks like this: 反序列化对象如下所示:

var xmlDeserializer = new RestSharp.Deserializers.XmlDeserializer();
results = xmlDeserializer.Deserialize<Vehicle>(response);

Where am I going wrong here? 我在哪里错了? As I would prefer not to modify the underlying data model, what Attributes can I add or modify to fix the problem? 由于我不想修改底层数据模型,我可以添加或修改哪些属性来解决问题?

You have marked your types with XML serializer attributes and data contract attributes , but the deserializer you are using, RestSharp.Deserializers.XmlDeserializer , does not support these attributes. 您已使用XML序列化程序属性数据协定属性标记了类型,但您使用的反序列化程序RestSharp.Deserializers.XmlDeserializer不支持这些属性。

Instead, as explained in its documentation , it supports the [DeserializeAs] attribute which allows for control of XML node name and element vs. attribute status. 相反,如其文档中所述 ,它支持[DeserializeAs]属性,该属性允许控制XML节点名称和元素与属性状态。

But as noted in @apocalypse's answer as well as this older question there is a special case in the documentation regarding deserialization of element values into property values: 但正如@ apocalypse的回答以及这个较旧的问题所述,文档中有一个关于将元素值反序列化为属性值的特殊情况:

If the XML returned is like this: 如果返回的XML是这样的:

 <Response>Hello world</Response> 

There's no way to directly represent that in a C# class: 在C#类中没有办法直接表示它:

 public class Response { } 

You need something to hold the value of the Response element. 您需要一些东西来保存Response元素的值。 In this case, add a property called Value and it will be populated: 在这种情况下,添加一个名为Value的属性,它将被填充:

 public class Response { public string Value { get; set; } } 

This condition is checked for between searching for matching element names and matching attribute names. 在搜索匹配的元素名称和匹配的属性名称之间检查此条件。

Ie if your rename Description to Value you will be able to deserialize that XML successfully. 即,如果重命名Description to Value您将能够成功地反序列化该XML。 ( Sample fiddle #1 .) 示例小提琴#1 。)

However, it appears you do not wish to rename your Description property. 但是,您似乎不希望重命名Description属性。 If so, you can instead apply [DeserializeAs(Name = "Value")] to it and the special case will again apply: 如果是这样,您可以将[DeserializeAs(Name = "Value")]应用于它,特殊情况将再次适用:

public class Option
{
    public string Code { get; set; }

    [DeserializeAs(Name = "Value")]
    public string Description { get; set; }
}

Sample fiddle #2 . 样品小提琴#2

Finally, as an alternative solution you could switch to RestSharp.Deserializers.DotNetXmlDeserializer and use regular XmlSerializer attributes, specifically [XmlText] . 最后,作为替代解决方案,您可以切换到RestSharp.Deserializers.DotNetXmlDeserializer并使用常规XmlSerializer属性,特别是[XmlText] Thus your code would become: 因此,您的代码将成为:

var xmlDeserializer = new RestSharp.Deserializers.DotNetXmlDeserializer();
var results = xmlDeserializer.Deserialize<Vehicle>(response);

And your types would look like: 你的类型看起来像:

[XmlRoot("vehicle")]
public class Vehicle
{
    [XmlAttribute("found")]
    public bool Found { get; set; }

    [XmlElement("description")]
    public string Description { get; set; }

    [XmlElement("buildDate")]
    public string BuildDate { get; set; }

    [XmlElement("modelYear")]
    public string ModelYear { get; set; }

    [XmlArray("optionList")]
    [XmlArrayItem("option")]
    public List<Option> OptionList { get; set; }
}

public class Option
{
    [XmlAttribute("code")]
    public string Code { get; set; }

    [XmlText]
    public string Description { get; set; }
}

Sample fiddle #3 . 样品小提琴#3

Read docs: https://github.com/restsharp/RestSharp/wiki/Deserialization 阅读文档: https//github.com/restsharp/RestSharp/wiki/Deserialization

Change Description property to Value property and it will work (in Option class). Description属性更改为Value属性,它将起作用(在Option类中)。

Can't give you better answer because I have never used RestSharp :) 无法给你更好的答案因为我从未使用过RestSharp :)

In the XML, the value you want isn't an inner XmlElement - it's the current XmlElement's value. 在XML中,您想要的值不是内部XmlElement - 它是当前XmlElement的值。

You could mark the Option class' Description property with XmlText instead of XmlElement . 您可以使用XmlText而不是XmlElement标记Option类的Description属性。

See related answer . 相关答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM