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