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

Top*_*000 2 c# xml restsharp deserialization

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

以下是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>
Run Code Online (Sandbox Code Playgroud)

以下是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; }
}
Run Code Online (Sandbox Code Playgroud)

反序列化对象如下所示:

var xmlDeserializer = new RestSharp.Deserializers.XmlDeserializer();
results = xmlDeserializer.Deserialize<Vehicle>(response);
Run Code Online (Sandbox Code Playgroud)

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

dbc*_*dbc 6

您已使用XML序列化程序属性数据协定属性标记了类型,但您使用的反序列化程序RestSharp.Deserializers.XmlDeserializer不支持这些属性.

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

但正如@ apocalypse的回答以及这个较旧的问题所述,文档中有一个特殊情况,即将元素值反序列化为属性值:

如果返回的XML是这样的:

<Response>Hello world</Response>
Run Code Online (Sandbox Code Playgroud)

在C#类中没有办法直接表示它:

public class Response {
}
Run Code Online (Sandbox Code Playgroud)

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

public class Response {
     public string Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

即如果您重命名DescriptionValue您将能够成功反序化该XML.(示例小提琴#1.)

但是,您似乎不希望重命名您的Description财产.如果是这样,您可以申请[DeserializeAs(Name = "Value")],特殊情况将再次适用:

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

    [DeserializeAs(Name = "Value")]
    public string Description { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

样品小提琴#2.

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

var xmlDeserializer = new RestSharp.Deserializers.DotNetXmlDeserializer();
var results = xmlDeserializer.Deserialize<Vehicle>(response);
Run Code Online (Sandbox Code Playgroud)

你的类型看起来像:

[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; }
}
Run Code Online (Sandbox Code Playgroud)

样品小提琴#3.