Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将NameValueCollection转换为JSON字符串?_C#_.net_Asp.net_Json_Namevaluecollection - Fatal编程技术网

C# 如何将NameValueCollection转换为JSON字符串?

C# 如何将NameValueCollection转换为JSON字符串?,c#,.net,asp.net,json,namevaluecollection,C#,.net,Asp.net,Json,Namevaluecollection,我试过: NameValueCollection Data = new NameValueCollection(); Data.Add("foo","baa"); string json = new JavaScriptSerializer().Serialize(Data); 它返回:[“foo”]I expected{“foo”:“baa”} 如何执行此操作?NameValueCollection不是IDictionary,因此JavaScriptSerializer无法按预期

我试过:

  NameValueCollection Data = new NameValueCollection();
  Data.Add("foo","baa");
  string json = new JavaScriptSerializer().Serialize(Data);
它返回:
[“foo”]
I expected
{“foo”:“baa”}

如何执行此操作?

NameValueCollection
不是IDictionary,因此
JavaScriptSerializer
无法按预期直接序列化它。您需要首先将其转换为字典,然后将其序列化

更新:以下是关于每个键的多个值的问题,调用
nvc[key]
只会返回逗号分隔的值,这可能是正确的。如果没有,可以随时调用
GetValues
,并决定如何适当地处理这些值。更新了下面的代码以显示一种可能的方法

public class StackOverflow_7003740
{
    static Dictionary<string, object> NvcToDictionary(NameValueCollection nvc, bool handleMultipleValuesPerKey)
    {
        var result = new Dictionary<string, object>();
        foreach (string key in nvc.Keys)
        {
            if (handleMultipleValuesPerKey)
            {
                string[] values = nvc.GetValues(key);
                if (values.Length == 1)
                {
                    result.Add(key, values[0]);
                }
                else
                {
                    result.Add(key, values);
                }
            }
            else
            {
                result.Add(key, nvc[key]);
            }
        }

        return result;
    }

    public static void Test()
    {
        NameValueCollection nvc = new NameValueCollection();
        nvc.Add("foo", "bar");
        nvc.Add("multiple", "first");
        nvc.Add("multiple", "second");

        foreach (var handleMultipleValuesPerKey in new bool[] { false, true })
        {
            if (handleMultipleValuesPerKey)
            {
                Console.WriteLine("Using special handling for multiple values per key");
            }
            var dict = NvcToDictionary(nvc, handleMultipleValuesPerKey);
            string json = new JavaScriptSerializer().Serialize(dict);
            Console.WriteLine(json);
            Console.WriteLine();
        }
    }
}
公共类堆栈溢出\u 7003740
{
静态字典NVCTO字典(NameValueCollection nvc、bool handleMultipleValuesPerKey)
{
var result=newdictionary();
foreach(nvc.Keys中的字符串键)
{
if(handleMultipleValuesPerKey)
{
字符串[]值=nvc.GetValues(键);
如果(values.Length==1)
{
结果。添加(键,值[0]);
}
其他的
{
结果。添加(键、值);
}
}
其他的
{
结果.添加(键,nvc[键]);
}
}
返回结果;
}
公共静态无效测试()
{
NameValueCollection nvc=新的NameValueCollection();
nvc.添加(“foo”、“bar”);
nvc.添加(“多个”、“第一个”);
nvc.添加(“多个”、“第二个”);
foreach(新bool[]{false,true}中的var handleMultipleValuesPerKey)
{
if(handleMultipleValuesPerKey)
{
WriteLine(“对每个键的多个值使用特殊处理”);
}
var dict=NvcToDictionary(nvc,handleMultipleValuesPerKey);
string json=new JavaScriptSerializer().Serialize(dict);
Console.WriteLine(json);
Console.WriteLine();
}
}
}

如果您的词典不打算包含许多条目,您可以使用以下类:
System.Collections.Specialized.ListDictionary

序列化NameValueCollection的一种方法是首先将其转换为Dictionary,然后序列化字典。要转换为字典,请执行以下操作:

thenvc.AllKeys.ToDictionary(k => k, k => thenvc[k]);
var json = new JavaScriptSerializer().Serialize(dict);
// you get {"Foo":"baa"}
如果需要经常进行转换,还可以创建NameValueCollection的扩展方法:

public static class NVCExtender
{
    public static IDictionary<string, string> ToDictionary(
                                        this NameValueCollection source)
    {
        return source.AllKeys.ToDictionary(k => k, k => source[k]);
    }
}
然后可以序列化字典:

thenvc.AllKeys.ToDictionary(k => k, k => thenvc[k]);
var json = new JavaScriptSerializer().Serialize(dict);
// you get {"Foo":"baa"}
但是NameValueCollection对于一个键可以有多个值,例如:

NameValueCollection Data = new NameValueCollection();
Data.Add("Foo", "baa");
Data.Add("Foo", "again?");
如果您将其序列化,您将得到
{“Foo”:“baa,再次?”}

您可以修改转换器以生成
IDictionary

public static IDictionary<string, string[]> ToDictionary(
                                    this NameValueCollection source)
{
    return source.AllKeys.ToDictionary(k => k, k => source.GetValues(k));
}
publicstaticidictionary到dictionary(
此名称(收集源)
{
返回source.AllKeys.ToDictionary(k=>k,k=>source.GetValues(k));
}

因此,您可以获得如下序列化值:
{“Foo”:[“baa”,“再次?”]}

为了完整性,并且因为问题不断被问到(例如),只要您使用的是Json.NET或
DataContractJsonSerializer
(而不是
JavaScriptSerializer
),您可以使用并将
NameValueCollection
包装在
IDictionary
适配器中,并使用完全支持序列化任意字典的任何序列化程序对其进行序列化

一旦此类适配器如下所示:

public class NameValueCollectionDictionaryAdapter<TNameValueCollection> : IDictionary<string, string[]>
    where TNameValueCollection : NameValueCollection, new()
{
    readonly TNameValueCollection collection;

    public NameValueCollectionDictionaryAdapter() : this(new TNameValueCollection()) { }

    public NameValueCollectionDictionaryAdapter(TNameValueCollection collection)
    {
        this.collection = collection;
    }

    // Method instead of a property to guarantee that nobody tries to serialize it.
    public TNameValueCollection 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);
        if (value == null)
            collection.Add(key, null);
        else
            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)
    {
        return (value = collection.GetValues(key)) != null;
    }

    public ICollection<string[]> Values
    {
        get
        {
            return new ReadOnlyCollectionAdapter<KeyValuePair<string, string[]>, string[]>(this, p => p.Value);
        }
    }

    public string[] this[string key]
    {
        get
        {
            var value = collection.GetValues(key);
            if (value == null)
                throw new KeyNotFoundException(key);
            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
}

public static class NameValueCollectionExtensions
{
    public static NameValueCollectionDictionaryAdapter<TNameValueCollection> ToDictionaryAdapter<TNameValueCollection>(this TNameValueCollection collection)
        where TNameValueCollection : NameValueCollection, new()
    {
        if (collection == null)
            throw new ArgumentNullException();
        return new NameValueCollectionDictionaryAdapter<TNameValueCollection>(collection);
    }
}

public class ReadOnlyCollectionAdapter<TIn, TOut> : CollectionAdapterBase<TIn, TOut, ICollection<TIn>>
{
    public ReadOnlyCollectionAdapter(ICollection<TIn> collection, Func<TIn, TOut> toOuter)
        : base(() => collection, toOuter)
    {
    }

    public override void Add(TOut item) { throw new NotImplementedException(); }

    public override void Clear() { throw new NotImplementedException(); }

    public override bool IsReadOnly { get { return true; } }

    public override bool Remove(TOut item) { throw new NotImplementedException(); }
}

public abstract class CollectionAdapterBase<TIn, TOut, TCollection> : ICollection<TOut> 
    where TCollection : ICollection<TIn>
{
    readonly Func<TCollection> getCollection;
    readonly Func<TIn, TOut> toOuter;

    public CollectionAdapterBase(Func<TCollection> getCollection, Func<TIn, TOut> toOuter)
    {
        if (getCollection == null || toOuter == null)
            throw new ArgumentNullException();
        this.getCollection = getCollection;
        this.toOuter = toOuter;
    }

    protected TCollection Collection { get { return getCollection(); } }

    protected TOut ToOuter(TIn inner) { return toOuter(inner); }

    #region ICollection<TOut> Members

    public abstract void Add(TOut item);

    public abstract void Clear();

    public virtual bool Contains(TOut item)
    {
        var comparer = EqualityComparer<TOut>.Default;
        foreach (var member in Collection)
            if (comparer.Equals(item, ToOuter(member)))
                return true;
        return false;
    }

    public void CopyTo(TOut[] array, int arrayIndex)
    {
        foreach (var item in this)
            array[arrayIndex++] = item;
    }

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

    public abstract bool IsReadOnly { get; }

    public abstract bool Remove(TOut item);

    #endregion

    #region IEnumerable<TOut> Members

    public IEnumerator<TOut> GetEnumerator()
    {
        foreach (var item in Collection)
            yield return ToOuter(item);
    }

    #endregion

    #region IEnumerable Members

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

    #endregion
}
string json = JsonConvert.SerializeObject(Data, Formatting.Indented, new NameValueJsonConverter<NameValueCollection>());
注:

  • 使用适配器可能比简单地创建一个复制的字典更有效,并且应该与任何完全支持字典序列化的序列化程序配合使用


    在将
    NameValueCollection
    与任何其他需要某种
    IDictionary
    的代码一起使用时,适配器可能也很有用-这是适配器模式的基本优势

  • 也就是说,
    JavaScriptSerializer
    不能与适配器一起使用,因为该序列化程序不能序列化实现
    IDictionary
    的任意类型,该类型也不能从
    字典继承。有关详细信息,请参阅


  • 使用
    DataContractJsonSerializer
    时,可以使用该机制将
    NameValueCollection
    替换为序列化图中的适配器


  • 使用Json.NET时,可以使用适配器替换
    NameValueCollection
    ,例如:

    public class NameValueJsonConverter<TNameValueCollection> : JsonConverter
        where TNameValueCollection : NameValueCollection, new()
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(TNameValueCollection).IsAssignableFrom(objectType);
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.SkipComments().TokenType == JsonToken.Null)
                return null;
    
            // Reuse the existing NameValueCollection if present
            var collection = (TNameValueCollection)existingValue ?? new TNameValueCollection();
            var dictionaryWrapper = collection.ToDictionaryAdapter();
    
            serializer.Populate(reader, dictionaryWrapper);
    
            return collection;
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var collection = (TNameValueCollection)value;
            var dictionaryWrapper = new NameValueCollectionDictionaryAdapter<TNameValueCollection>(collection);
            serializer.Serialize(writer, dictionaryWrapper);
        }
    }
    
    public static partial class JsonExtensions
    {
        public static JsonReader SkipComments(this JsonReader reader)
        {
            while (reader.TokenType == JsonToken.Comment && reader.Read())
                ;
            return reader;
        }
    }
    
    公共类名称值JsonConverter:JsonConverter
    其中TNameValueCollection:NameValueCollection,new()
    {
    公共覆盖布尔CanConvert(类型objectType)
    {
    返回类型(TNameValueCollection).IsAssignableFrom(objectType);
    }
    公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
    {
    if(reader.SkipComments().TokenType==JsonToken.Null)
    返回null;
    //重用现有的NameValueCollection(如果存在)
    var collection=(TNameValueCollection)现有值??新的TNameValueCollection();
    var dictionaryWrapper=collection.ToDictionaryAdapter();
    序列化程序。填充(读取器、字典说话者);
    回收;
    }
    公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
    {
    var集合=(TNameValueCollection)值;
    var DictionaryRapper=新名称ValueCollectionDictionaryAdapter(集合);
    serializer.Serialize(编写器、字典说话者);
    }
    }
    公共静态部分类JsonExtensions
    {
    公共静态JsonReader SkipComments(此JsonReader阅读器)
    {
    while(reader.TokenType==JsonToken.Comment&&reader.Read())
    ;
    返回读取器;
    }
    }
    
    可用于以下用途,例如:

    public class NameValueCollectionDictionaryAdapter<TNameValueCollection> : IDictionary<string, string[]>
        where TNameValueCollection : NameValueCollection, new()
    {
        readonly TNameValueCollection collection;
    
        public NameValueCollectionDictionaryAdapter() : this(new TNameValueCollection()) { }
    
        public NameValueCollectionDictionaryAdapter(TNameValueCollection collection)
        {
            this.collection = collection;
        }
    
        // Method instead of a property to guarantee that nobody tries to serialize it.
        public TNameValueCollection 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);
            if (value == null)
                collection.Add(key, null);
            else
                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)
        {
            return (value = collection.GetValues(key)) != null;
        }
    
        public ICollection<string[]> Values
        {
            get
            {
                return new ReadOnlyCollectionAdapter<KeyValuePair<string, string[]>, string[]>(this, p => p.Value);
            }
        }
    
        public string[] this[string key]
        {
            get
            {
                var value = collection.GetValues(key);
                if (value == null)
                    throw new KeyNotFoundException(key);
                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
    }
    
    public static class NameValueCollectionExtensions
    {
        public static NameValueCollectionDictionaryAdapter<TNameValueCollection> ToDictionaryAdapter<TNameValueCollection>(this TNameValueCollection collection)
            where TNameValueCollection : NameValueCollection, new()
        {
            if (collection == null)
                throw new ArgumentNullException();
            return new NameValueCollectionDictionaryAdapter<TNameValueCollection>(collection);
        }
    }
    
    public class ReadOnlyCollectionAdapter<TIn, TOut> : CollectionAdapterBase<TIn, TOut, ICollection<TIn>>
    {
        public ReadOnlyCollectionAdapter(ICollection<TIn> collection, Func<TIn, TOut> toOuter)
            : base(() => collection, toOuter)
        {
        }
    
        public override void Add(TOut item) { throw new NotImplementedException(); }
    
        public override void Clear() { throw new NotImplementedException(); }
    
        public override bool IsReadOnly { get { return true; } }
    
        public override bool Remove(TOut item) { throw new NotImplementedException(); }
    }
    
    public abstract class CollectionAdapterBase<TIn, TOut, TCollection> : ICollection<TOut> 
        where TCollection : ICollection<TIn>
    {
        readonly Func<TCollection> getCollection;
        readonly Func<TIn, TOut> toOuter;
    
        public CollectionAdapterBase(Func<TCollection> getCollection, Func<TIn, TOut> toOuter)
        {
            if (getCollection == null || toOuter == null)
                throw new ArgumentNullException();
            this.getCollection = getCollection;
            this.toOuter = toOuter;
        }
    
        protected TCollection Collection { get { return getCollection(); } }
    
        protected TOut ToOuter(TIn inner) { return toOuter(inner); }
    
        #region ICollection<TOut> Members
    
        public abstract void Add(TOut item);
    
        public abstract void Clear();
    
        public virtual bool Contains(TOut item)
        {
            var comparer = EqualityComparer<TOut>.Default;
            foreach (var member in Collection)
                if (comparer.Equals(item, ToOuter(member)))
                    return true;
            return false;
        }
    
        public void CopyTo(TOut[] array, int arrayIndex)
        {
            foreach (var item in this)
                array[arrayIndex++] = item;
        }
    
        public int Count { get { return Collection.Count; } }
    
        public abstract bool IsReadOnly { get; }
    
        public abstract bool Remove(TOut item);
    
        #endregion
    
        #region IEnumerable<TOut> Members
    
        public IEnumerator<TOut> GetEnumerator()
        {
            foreach (var item in Collection)
                yield return ToOuter(item);
        }
    
        #endregion
    
        #region IEnumerable Members
    
        IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
    
        #endregion
    }
    
    string json = JsonConvert.SerializeObject(Data, Formatting.Indented, new NameValueJsonConverter<NameValueCollection>());
    
    string json=JsonConvert.SerializeOb