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

时间:2017-10-30 20:37:06

标签: c# xml deserialization restsharp

我无法从API调用反序列化XML响应。我的'Option'对象的属性'Description'为空。

以下是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>

以下是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; }
}

反序列化对象如下所示:

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

我在哪里错了?由于我不想修改底层数据模型,我可以添加或修改哪些属性来解决问题?

3 个答案:

答案 0 :(得分:6)

您已使用XML serializer attributesdata contract attributes标记了自己的类型,但您使用的反序列化程序RestSharp.Deserializers.XmlDeserializer不支持这些属性。

相反,正如其documentation中所解释的,它支持[DeserializeAs]属性,该属性允许控制XML节点名称和元素与属性状态。

但正如@apocalypse's answer以及this older question中所述,文档中有关于将元素值反序列化为属性值的特殊情况:

  

如果返回的XML是这样的:

<Response>Hello world</Response>
     

无法直接在C#类中表示:

public class Response {
}
     

您需要一些东西来保存Response元素的值。在这   case,添加一个名为Value的属性,它将被填充:

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

在搜索匹配元素之间检查此条件   名称和匹配的属性名称。

即。如果您将Description重命名为Value,则可以成功反序化该XML。 (Sample fiddle #1。)

但是,您似乎不希望重命名Description媒体资源。如果是这样,您可以将[DeserializeAs(Name = "Value")]应用于它,特殊情况将再次适用:

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

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

示例fiddle #2

最后,作为替代解决方案,您可以切换到RestSharp.Deserializers.DotNetXmlDeserializer并使用常规XmlSerializer属性,特别是[XmlText]。因此,您的代码将成为:

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

你的类型看起来像:

[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; }
}

示例fiddle #3

答案 1 :(得分:2)

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

Description属性更改为Value属性,它将起作用(在Option类中)。

无法给你更好的答案,因为我从未使用过RestSharp:)

答案 2 :(得分:1)

在XML中,您想要的值不是内部XmlElement - 它是当前XmlElement的值。

您可以标记Option班级&#39; Description XmlText属性,而不是XmlElement

请参阅related answer