2011-08-09 23 views

Respuesta

34

NameValueCollection no es un IDictionary, por lo que JavaScriptSerializer no puede serializarlo como lo espera directamente. Primero tendrá que convertirlo en un diccionario y luego serializarlo.

Actualización: si tiene preguntas sobre los valores múltiples por tecla, la llamada al nvc[key] simplemente los devolverá separados por una coma, lo que puede estar bien. Si no, uno siempre puede llamar al GetValues y decidir qué hacer con los valores de forma apropiada. Actualizado el código a continuación para mostrar una posible forma.

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(); 
     } 
    } 
} 
+3

'NameValueCollection' podría tener varios valores por clave, esto no soluciona ese problema. – zzzzBov

+0

¡Este método probablemente cause excepciones! La razón por la que existe NameValueCollection (y .NET no usa un diccionario a veces) es permitir múltiples valores por clave. Un diccionario requiere una y solo una clave por valor. –

+1

El método no lanzará una excepción. Si hay varias teclas, 'nvc [key]' simplemente las devolverá unidas por un caracter ','. Pero, para completar, actualicé la respuesta para ser más explícito al respecto. – carlosfigueira

3

Si el diccionario no está destinado a contener muchas entradas, puede utilizar la clase: System.Collections.Specialized.ListDictionary

33

Una forma de serializar NameValueCollection está convirtiendo en primer lugar al diccionario y luego serializar el diccionario. Para convertir al diccionario:

thenvc.AllKeys.ToDictionary(k => k, k => thenvc[k]); 

Si usted tiene que hacer la conversión con frecuencia, también puede crear un método de extensión a NameValueCollection:

public static class NVCExtender 
{ 
    public static IDictionary<string, string> ToDictionary(
             this NameValueCollection source) 
    { 
     return source.AllKeys.ToDictionary(k => k, k => source[k]); 
    } 
} 

lo que puede hacer la conversión en una línea como la siguiente:

NameValueCollection Data = new NameValueCollection(); 
Data.Add("Foo", "baa"); 

var dict = Data.ToDictionary(); 

A continuación, puede serializar el diccionario:

var json = new JavaScriptSerializer().Serialize(dict); 
// you get {"Foo":"baa"} 

Pero NameValueCollection puede tener varios valores para una clave, por ejemplo:

NameValueCollection Data = new NameValueCollection(); 
Data.Add("Foo", "baa"); 
Data.Add("Foo", "again?"); 

Si serializa este obtendrá {"Foo":"baa,again?"}.

puede modificar el convertidor para producir IDictionary<string, string[]> lugar:

public static IDictionary<string, string[]> ToDictionary(
            this NameValueCollection source) 
{ 
    return source.AllKeys.ToDictionary(k => k, k => source.GetValues(k)); 
} 

para que pueda obtener el valor serializado como esto: {"Foo":["baa","again?"]}.