2010-05-23 12 views
12

cada vez que intento para serializar el diccionario Me da la excepción:Problemas con JSON Serialize Diccionario <Enum, Int32>

System.ArgumentException: Type 
'System.Collections.Generic.Dictionary`2[[Foo.DictionarySerializationTest+TestEnum, Foo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' 
is not supported for serialization/deserialization of a dictionary, 
keys must be strings or object 

Mi caso de prueba es:

public class DictionarySerializationTest 
{ 
    public enum TestEnum { A, B, C } 
    //tried with numbers, too: public enum TestEnum { A = 1, B = 2, C = 3 } 

    public void SerializationTest() 
    { 
    Dictionary<TestEnum, Int32> data = new Dictionary<TestEnum, Int32>(); 

    data.Add(TestEnum.A, 1); 
    data.Add(TestEnum.B, 2); 
    data.Add(TestEnum.C, 3); 

    JavaScriptSerializer serializer = new JavaScriptSerializer(); 
    String result = serializer.Serialize(data); 
    // Throws 
    } 

    public void SerializationToObjectTest() 
    { 
    Dictionary<object, Int32> data = new Dictionary<object, Int32>(); 

    data.Add(Enum.ToObject(typeof(TestEnum), TestEnum.A), 1); 
    data.Add(Enum.ToObject(typeof(TestEnum), TestEnum.B), 2); 
    data.Add(Enum.ToObject(typeof(TestEnum), TestEnum.C), 3); 

    JavaScriptSerializer serializer = new JavaScriptSerializer(); 
    String result = serializer.Serialize(data); 
    // Throws 
    } 

    public void SerializationStringTest() 
    { 
    Dictionary<String, Int32> data = new Dictionary<String, Int32>(); 

    data.Add(TestEnum.A.ToString(), 1); 
    data.Add(TestEnum.B.ToString(), 2); 
    data.Add(TestEnum.C.ToString(), 3); 

    JavaScriptSerializer serializer = new JavaScriptSerializer(); 
    String result = serializer.Serialize(data); 
    // Succeeds 
    } 

} 

Por supuesto que podría utilizar .ToString() cada vez que ingrese algo en el Diccionario, pero dado que se usa con bastante frecuencia en métodos relevantes para el rendimiento, preferiría usar la enumeración.

Mi única solución es utilizar .ToString() y convertir antes de entrar en las regiones críticas de rendimiento, pero eso es torpe y tendría que cambiar la estructura de mi código para poder serializar los datos.

¿Alguien tiene una idea de cómo puedo serializar el diccionario como <Enum, Int32>?

Utilizo System.Web.Script.Serialization.JavaScriptSerializer para la serialización.

ACTUALIZACIÓN:

me cambió a Dictionary<String, Int32> ahora y funciona, pero espero que alguien muestra una solución, ya que no me gusta mucho el uso de cadenas en lugar de un tipo de enumeración segura.

+0

posible duplicado de (http: // stackoverflow.com/questions/5597349/how-do-i-convert-a-dictionary-to-a-json-string-in-c) –

Respuesta

18

Sé que es tarde, pero tal vez alguien más pueda hacer uso de ella en el futuro. Se puede lograr lo que necesita el uso de LINQ:

Dictionary<TestEnum, Int32> data = new Dictionary<TestEnum, Int32>(); 

data.Add(TestEnum.A, 1); 
data.Add(TestEnum.B, 2); 
data.Add(TestEnum.C, 3); 

JavaScriptSerializer serializer = new JavaScriptSerializer(); 
Dictionary<string, Int32> dataToSerialize = data.Keys.ToDictionary(p => p.ToString(), p => data[p]); 
string dataSerialized = serializer.Serialize(dataToSerialize); 
+0

No es demasiado tarde ... Sigue siendo útil en 2016 –

+0

Todavía recomendaría usar Json.NET como se indica en la documentación de la clase JavaScriptSerializador: https://msdn.microsoft.com/en-us/library/system.web.script .serialization.javascriptserializer (v = vs.110) .aspx – kimbaudi

0

Creo que tiene problemas porque TestEnum está declarado como private enum. Intente marcarlo como public enum. El serializador necesita poder encontrar su enumeración a través de la reflexión para serializarlo.

También de acuerdo con Docs, las enumeraciones deben tener valores enteros. Así que es posible que desee escribir:

public enum TestEnum { A = 1, B = 2, C =3 } 

Además, los documentos dicen que esta enumeración solo conseguirá asignada a su valor entero correspondiente durante la serialización. Por lo tanto, dependiendo de lo que esté haciendo en el otro extremo, String s puede ser más expresivo y fácil de trabajar.

+0

Gracias por la sugerencia, pero cambiar la enumeración a pública y agregar valores enteros no cambió cualquier cosa. – dbemerlin

0

Excepción dice "claves deben ser cadenas o objeto" a fin de tratar

data.Add(Enum.ToObject(typeof(TestEnum), TestEnum.A)); 
data.Add(Enum.ToObject(typeof(TestEnum), TestEnum.B)); 
data.Add(Enum.ToObject(typeof(TestEnum), TestEnum.C)); 

no he probado que, sin embargo, sólo una suposición.

+0

Parece que no acepta todos los tipos de objetos, el error sigue siendo el mismo. Gracias por la sugerencia, sin embargo. – dbemerlin

0

He creado extensión JavaScriptSerializer DeserializeDictionary- ver http://geekswithblogs.net/mnf/archive/2011/06/03/javascriptserializer-extension-deserializedictionarytkey-tvalue.aspx

public static Dictionary<TKey, TValue> DeserializeDictionary<TKey, TValue>(this JavaScriptSerializer jss, string jsonText) 
{ 
    var dictWithStringKey = jss.Deserialize<Dictionary<string,TValue>>(jsonText); 
    var dict=dictWithStringKey.ToDictionary(de => jss.ConvertToType<TKey>(de.Key),de => de.Value); 
     return dict; 
} 
5

Uso Newtonsoft (Newtonsoft.Json.dll) para serializar el objeto Dictionary y que estaría bien. Es una biblioteca popular de terceros que tendrías que descargar e incluir en tu proyecto como referencia.

Consulte el siguiente ejemplo: [? ¿Cómo se convierte un diccionario a una cadena JSON en C#]

var _validationInfos = new Dictionary<ImportField, ValidationInfo>(); 
var serializedData = JsonConvert.SerializeObject(_validationInfos); 
+0

En estos días, incluso Microsoft recomienda utilizar la biblioteca de Newtonsoft JSON: https://msdn.microsoft.com/en-us/library/system.web.script.serialization. javascriptserializer (v = vs.110) .aspx – Mr47

Cuestiones relacionadas