Json   发布时间:2022-04-22  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了使用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": []
    }
  ]
}

大佬总结

以上是大佬教程为你收集整理的使用Json.Net序列化NameValueCollection的自定义子类全部内容,希望文章能够帮你解决使用Json.Net序列化NameValueCollection的自定义子类所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。