Newtonsoft.Json反序列化XmlAnyAttribute?

时间:2017-05-09 14:48:31

标签: c# json.net

我有一个有一个对象的类:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34283")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=true)]
public partial class Scores : baseModel
{
   private System.Xml.XmlAttribute[] anyAttrField;
   /// <remarks/>
   [System.Xml.Serialization.XmlAnyAttributeAttribute()]
   public System.Xml.XmlAttribute[] AnyAttr
  {
      get
      {
         return this.anyAttrField;
      }
      set
      {
         this.anyAttrField = value;
      }
   }
}

来自父类(它的片段):

public parial class LandingPage : baseModel
{
    private string projectNameField;
    private Scores scoresField;
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string projectName
    {
        get { return this.projectNameField; }
        set { this.projectNameField = value; }
    }
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public Scores scores
    {
        get { return this.scoresField; }
        set { this.scoresField = value }
    }
}

我试图使用的JSON字符串:

{
    "projectName":"PROJECTTEST",
    "scores":{
        "browLocker":100,
        "heavyAd":0,
        "walletRedirection":0
    }
}

NewtonSoft.JsonConvert忽略分数子字段...

如何轻松将其转换为工作?

1 个答案:

答案 0 :(得分:0)

鉴于您的Scores类型没有自己的属性可以序列化,您可以为其创建custom JsonConverter,将XmlAttribute []数组转换为Dictionary<string, string>然后序列化该字典代替Scores对象:

public class XmlAttributeArrayConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(XmlAttribute[]);
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var dict = serializer.Deserialize<Dictionary<string, string>>(reader);
        var doc = new XmlDocument();
        return dict.Select(p => { var a = doc.CreateAttribute(p.Key); a.Value = p.Value; return a; }).ToArray();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // TODO: determine how to represent XmlAttribute values with non-empty NamespaceURI - or throw an exception.
        var attributes = (IEnumerable<XmlAttribute>)value;
        var dict = attributes.ToDictionary(a => a.Name, a => a.Value);
        serializer.Serialize(writer, dict);
    }
}

class ScoresConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Scores);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var attributes = (XmlAttribute[])new XmlAttributeArrayConverter().ReadJson(reader, typeof(XmlAttribute[]), null, serializer);
        return new Scores { AnyAttr = attributes };
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var scores = (Scores)value;
        if (scores.AnyAttr == null)
            writer.WriteNull();
        else
        {
            new XmlAttributeArrayConverter().WriteJson(writer, scores.AnyAttr, serializer);
        }
    }
}

(注意我将一些逻辑提取到一个单独的XmlAttributeArrayConverter,以防它可能在其他地方使用。)

然后将其应用于Scores,如下所示:

[JsonConverter(typeof(ScoresConverter))]
public partial class Scores
{
}

示例fiddle

请注意,如果其中一个XML属性恰好位于命名空间中(大多数时间为none will be),则命名空间不会被序列化。如果您的属性可能具有名称空间,则需要决定如何将属性的全名转换为JSON属性名称。 {namespace}localname是一种可能性,即XName.ToString()使用的内容。

相关问题