使用Json.Net序列化NameValueCollection的自定义子类

我有以下类,我没有成功尝试序列化到Json.
class HL7 : NameValueCollection
{
  public List<HL7> Children { get; set; }
  public HL7()
  {
    Children = new List<HL7>();
  }
}

我已经像这样创建了对象并向其添加了数据:

HL7 hl7 = new HL7();
hl7.Add("a","123");
hl7.Add("b","456");
hl7.Children.Add(new HL7());
hl7.Children[0].Add("c","123");
hl7.Children[0].Add("d","456");

我打电话的时候

JsonConvert.SerializeObject(hl7)

我收到

["a","b"]

我期待以下:

{
  "a": "123","b": "456","Children": [
    {
      "c": "123","d": "456",}
  ]
}
这里有一些事情:

> Json.NET无法在没有自定义转换器的情况下序列化NameValueCollection,因为NameValueCollection实现了IEnumerable以迭代键,但没有实现IDictionary来迭代键和值.有关为何导致Json.NET出现问题的更全面解释,请参阅this answer.
>因为NameValueCollection实现了IEnumerable,Json.NET将您的类视为集合,因此将其序列化为JSON数组而不是具有命名属性的JSON对象.因此,您的孩子不是序列化的.同样,需要一个自定义转换器来解决这个问题.
>假设上述问题已解决,如果NameValueCollection的HL7子类碰巧有一个名为“Children”的键,则在序列化时会生成无效的JSON,即具有重复属性名称的对象.我建议移动名字和为了明确的序列化,将值转换为嵌套属性(命名为“Values”).
> NameValueCollection实际上可以为给定的键字符串提供多个字符串值,因此其条目值需要序列化为JSON数组而不是单个字符串.

将所有这些放在一起,以下代码

[JsonConverter(typeof(HL7Converter))]
public class HL7 : NameValueCollection
{
    public List<HL7> Children { get; set; }
    public HL7()
    {
        Children = new List<HL7>();
    }
}

public class HL7Converter : JsonConverter
{
    class HL7Proxy
    {
        public NameValueCollectionDictionaryWrapper Values { get; set; }
        public List<HL7> Children { get; set; }
    }


    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(HL7);
    }

    public override object ReadJson(JsonReader reader,Type objectType,object existingValue,JsonSerializer serializer)
    {
        var proxy = serializer.Deserialize<HL7Proxy>(reader);
        if (proxy == null)
            return existingValue;
        var hl7 = existingValue as HL7;
        if (hl7 == null)
            hl7 = new HL7();
        hl7.Add(proxy.Values.GetCollection());
        if (proxy.Children != null)
            hl7.Children.AddRange(proxy.Children);
        return hl7;
    }

    public override void WriteJson(JsonWriter writer,object value,JsonSerializer serializer)
    {
        HL7 hl7 = (HL7)value;
        if (hl7 == null)
            return;

        serializer.Serialize(writer,new HL7Proxy { Children = hl7.Children,Values = new NameValueCollectionDictionaryWrapper(hl7) });
    }
}

// Proxy dictionary to serialize & deserialize a NameValueCollection.  We use a proxy dictionary rather than a real dictionary because NameValueCollection is an ordered collection but the generic dictionary class is unordered.
public class NameValueCollectionDictionaryWrapper: IDictionary<string,string []>
{
    readonly NameValueCollection collection;

    public NameValueCollectionDictionaryWrapper()
        : this(new NameValueCollection())
    {
    }

    public NameValueCollectionDictionaryWrapper(NameValueCollection collection)
    {
        this.collection = collection;
    }

    // Method instead of a property to guarantee that nobody tries to serialize it.
    public NameValueCollection GetCollection()
    {
        return collection;
    }

    #region IDictionary<string,string[]> Members

    public void Add(string key,string[] value)
    {
        if (collection.GetValues(key) != null)
            throw new ArgumentException("Duplicate key " + key);
        foreach (var str in value)
            collection.Add(key,str);
    }

    public bool ContainsKey(string key)
    {
        return collection.GetValues(key) != null;
    }

    public ICollection<string> Keys
    {
        get {
            return collection.AllKeys;
        }
    }

    public bool Remove(string key)
    {
        bool found = ContainsKey(key);
        if (found)
            collection.Remove(key);
        return found;
    }

    public bool TryGetValue(string key,out string[] value)
    {
        value = collection.GetValues(key);
        return value != null;
    }

    public ICollection<string[]> Values
    {
        get {
            return Enumerable.Range(0,collection.Count).Select(i => collection.GetValues(i)).ToArray();
        }
    }

    public string[] this[string key]
    {
        get
        {
            var value = collection.GetValues(key);
            if (value == null)
                throw new KeyNotFoundException();
            return value;
        }
        set
        {
            Remove(key);
            Add(key,value);
        }
    }

    #endregion

    #region ICollection<keyvaluePair<string,string[]>> Members

    public void Add(keyvaluePair<string,string[]> item)
    {
        Add(item.Key,item.Value);
    }

    public void Clear()
    {
        collection.Clear();
    }

    public bool Contains(keyvaluePair<string,string[]> item)
    {
        string [] value;
        if (!TryGetValue(item.Key,out value))
            return false;
        return EqualityComparer<string[]>.Default.Equals(item.Value,value); // Consistent with Dictionary<TKey,TValue>
    }

    public void copyTo(keyvaluePair<string,string[]>[] array,int arrayIndex)
    {
        foreach (var item in this)
            array[arrayIndex++] = item;
    }

    public int Count
    {
        get { return collection.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(keyvaluePair<string,string[]> item)
    {
        if (Contains(item))
            return Remove(item.Key);
        return false;
    }

    #endregion

    #region IEnumerable<keyvaluePair<string,string[]>> Members

    public IEnumerator<keyvaluePair<string,string[]>> GetEnumerator()
    {
        foreach (string key in collection)
        {
            yield return new keyvaluePair<string,string[]>(key,collection.GetValues(key)); 
        }
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    #endregion
}

使用以下测试用例:

HL7 hl7 = new HL7();
        hl7.Add("a","123");
        hl7.Add("b","456");
        hl7.Add("Children","Children");
        hl7.Children.Add(new HL7());
        hl7.Children[0].Add("c","123");
        hl7.Children[0].Add("d","456");
        hl7.Children[0].Add("d","789");

        var json = JsonConvert.SerializeObject(hl7,Formatting.Indented);

        Debug.WriteLine(json);

提供以下JSON:

{
  "Values": {
    "a": [
      "123"
    ],"b": [
      "456"
    ],"Children": [
      "Children"
    ]
  },"Children": [
    {
      "Values": {
        "c": [
          "123"
        ],"d": [
          "456","789"
        ]
      },"Children": []
    }
  ]
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


AJAX是一种基于JavaScript和XML的技术,能够使网页实现异步交互,节省带宽和时间,提高用户体验。在使用AJAX时,需要通过解析JSON格式的数据,来获取所需要的数据。
在网页开发中,我们常常需要通过Ajax从后端获取数据并在页面中展示出来。其中,JSON是一种常用的数据格式。那么,在使用Ajax获取JSON数据后,如何将数据取出来呢?
在前端开发中,经常需要循环JSON对象数组进行数据操作。使用AJAX技术可以在不刷新页面的情况下异步获取数据。那么我们该如何循环JSON对象数组呢?下面我们通过一段代码来进行讲解。
AJAX(Asynchronous JavaScript and XML)是一种用于创建 Web 应用程序的技术,它使用 JavaScript 和 XML(或 JSON)来在后台异步传输数据。
AJAX技术被广泛应用于现代Web开发,它可以在无需重新加载页面的情况下,向服务器发出请求并更新页面,实现了异步更新的效果。而传递JSON数据是AJAX中比较常见的一种方法,下面是如何使用AJAX传递JSON数据的详细介绍。
Ajax是一种通过JavaScript和HTTP请求交互的技术,可以实现无需刷新页面的异步数据交互。在处理数据时,常常需要删除一些已存在的数据。本文将介绍如何使用Ajax删除JSON数据库中的数据。
在使用Ajax时,我们经常需要将数据格式化为JSON格式。JSON是一种轻量级数据交换格式,它以键值对的形式来表达数据。
AJAX是一种支持异步请求的技术,它可以让前端页面不用刷新就能向后台请求数据,并异步地展示给用户,提高了用户的体验感。其中,使用JSON格式化数据可以帮助我们更方便快捷地处理返回的数据。
AJAX是一种前端技术,可以通过异步请求来获取数据,并在页面上更新它们。JSON是一种轻量级的数据交换格式,因为它易于读取和编写,因此在Web应用程序中被广泛使用。AJAX传送JSON数据是一种常见的技术,可以让Web应用
在前端开发中,ajax是很常见的技术,它可以在不刷新整个页面的情况下请求服务器数据和更新部分页面。而当需要遍历多个json文件时,可以使用ajax循环遍历来实现。
AJAX技术是实现Web页面无刷新的最佳方式。其中json解析是一种常用的技术,它可以通过AJAX异步请求数据,再用json解析器将返回的json字符串解析成JavaScript对象。下面就让我们来看看如何使用ajax解析json数据。
AJAX技术可以在不刷新整个WEB页面的情况下与服务器进行数据交换,这使得在现代WEB应用中使用AJAX技术变得非常普遍。而访问JSON数组是一种非常常见的AJAX操作。在本文中,我们将向您展示如何使用AJAX技术循环遍历JSO
Ajax(Asynchronous JavaScript and XML)是一种在不重新加载整个页面的情况下更新网页的技术。它可以向服务器发送请求并接收响应,然后使用JavaScript动态地显示内容。
AJAX技术可以帮助我们实现对JSON数据库的循环读取。下面我们来介绍一下如何使用AJAX技术读取JSON数据库。
AJAX是一种在Web应用中实现局部更新的技术。而JSON是一种数据格式,非常适合用来表示数据。在AJAX中,我们经常需要从后端服务器获取JSON格式的数据,在前端页面中进行处理。那么,如何解析JSON数据呢?
AJAX是一种在不重新载入整个页面的情况下,能够更新部分页面的技术,它可以通过异步通信获取后台数据,其中JSON作为一种轻量级数据交换格式,常常被用来传递数据。在使用AJAX接收到后台传送的JSON数据后,需要进行解
在网站开发中,为了减少页面的刷新,异步加载技术成为了开发中越来越常见的一种技术,而 AJAX 技术就是一种常见的实现方式。其中,通过循环读取 JSON 数据能够实现页面内容的实时更新。
在前端开发中,经常需要从服务器获取JSON数据来展示在页面上,而循环遍历这些数据就需要使用AJAX以及JavaScript。本文将介绍如何使用AJAX和JavaScript来循环遍历JSON数据。
在前端开发中,我们常常需要通过 Ajax 请求后端接口获取数据并进行展示。而 JSON 数据则是一种常见的数据格式,因此我们需要了解如何通过 Ajax 获取 JSON 数据。
在使用ajax传递数据时,我们通常会遇到传递json数据类型的情况。那么,接下来我们就来仔细了解一下如何使用ajax传递json数据类型。