C# - 在XML反序列化时处理可以是单个属性和数组的属性

时间:2017-08-30 12:04:13

标签: c# json xml

我有一个看起来像我需要反序列化的XML:

<?xml version="1.0" encoding="utf-8" ?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Countries>
      <Country>
        <CountryCode>CN</CountryCode>
        <CurrentStatus>Active</CurrentStatus>
      </Country>
    </Countries>

    <Countries>
      <Country>
        <CountryCode>AU</CountryCode>
        <CurrentStatus>Cancelled</CurrentStatus>
      </Country>
      <Country>
        <CountryCode>CN</CountryCode>
        <CurrentStatus>Cancelled</CurrentStatus>
      </Country>
      <Country>
        <CountryCode>US</CountryCode>
        <CurrentStatus>Active</CurrentStatus>
      </Country>
    </Countries>

    <Countries xsi:nil="true" />
</Root>

我的问题是,国家可以将国家/地区视为单一和数组,如您所见。为了让它正常工作,我现在将它作为object类型,但它很难处理。解决这个问题的最佳解决方案是什么?我将它转换为json,因为我们所有其他系统都使用它,这是我们唯一的XML文件。

public class Country
{

    [JsonProperty("CountryCode")]
    public string CountryCode { get; set; }

    [JsonProperty("CurrentStatus")]
    public string CurrentStatus { get; set; }
}

public class CountryInfo
{
    [JsonProperty("Country")]
    public object Country { get; set; }

    //Does not work
    //[JsonProperty("Country")]
    //public IList<Country> Country { get; set; }
}

public class Root
{
    [JsonProperty("Countries")]
    public IList<CountryInfo> Countries { get; set; }
}

public class ExampleCountry
{
    [JsonProperty("Root")]
    public Root Root { get; set; }
}

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
string json = JsonConvert.SerializeXmlNode(xmlDoc);
var exampleCountries = JsonConvert.DeserializeObject<ExampleCountry>(json);

更新

如果我启用public IList<Country> Country { get; set; },我会收到以下错误:

  

Newtonsoft.Json.JsonSerializationException:'无法反序列化   当前的JSON对象(例如{“name”:“value”})到类型中   'System.Collections.Generic.IList`1 []'因为类型需要a   要正确反序列化的JSON数组(例如[1,2,3])。

1 个答案:

答案 0 :(得分:1)

使用这个答案解决了它:

https://stackoverflow.com/a/18997172/3850405

public class CountryInfo
{
    [JsonProperty("Country")]
    [JsonConverter(typeof(SingleOrArrayConverter<Country>))]
    public IList<Country> Country { get; set; }
}

public class SingleOrArrayConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(List<T>));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        if (token.Type == JTokenType.Array)
        {
            return token.ToObject<List<T>>();
        }
        return new List<T> { token.ToObject<T>() };
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}