2010-05-23 14 views
12

ogni volta che provo per serializzare dizionario ottengo l'eccezione:Problemi con JSON Serialize dizionario <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 

mio Testcase è:

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 
    } 

} 

Naturalmente potrei usare .ToString() ogni volta che inserire qualcosa nel dizionario, ma dal momento che è usato abbastanza spesso in metodi rilevanti per le prestazioni, preferirei usare l'enum.

La mia unica soluzione è usare .ToString() e convertire prima di entrare nelle regioni critiche per le prestazioni, ma è maldestro e dovrei cambiare la mia struttura di codice solo per poter serializzare i dati.

Qualcuno ha un'idea di come potrei serializzare il dizionario come <Enum, Int32>?

Uso System.Web.Script.Serialization.JavaScriptSerializer per la serializzazione.

UPDATE:

sono passato a Dictionary<String, Int32> ora e funziona, ma spero che qualcuno mostra una soluzione in quanto non ho davvero come l'utilizzo di stringhe al posto di un tipo enum sicura.

+0

possibile duplicato (http: // StackOverflow.it/questions/5597349/how-do-i-convert-a-dizionario-a-un-json-string-in-c) –

risposta

18

So che è tardi, ma forse qualcun altro può fare uso di esso in futuro. È possibile ottenere quello che vi serve utilizzando 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

Non troppo tardi ... Ancora utile nel 2016 –

+0

Mi raccomando ancora di utilizzare Json.NET come indicato nella documentazione della classe JavaScriptSerializer: https://msdn.microsoft.com/en-us/library/system.web.script .serialization.javascriptserializer (v = vs.110) .aspx – kimbaudi

0

Penso che tu abbia problemi perché TestEnum è dichiarato come private enum. Prova a contrassegnarlo come public enum. Il serializzatore deve essere in grado di trovare l'enumerazione tramite riflessione per serializzarlo.

Inoltre, secondo lo Docs, l'enumerazione deve avere valori interi. Così si potrebbe desiderare di scrivere:

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

Inoltre, i documenti dicono che questo sarà solo enum ottenere mappato al suo valore intero corrispondente durante la serializzazione. Quindi, a seconda di ciò che stai facendo dall'altra parte, String s potrebbe essere più espressivo e più facile da lavorare.

+0

Grazie per il suggerimento, ma la modifica dell'enumerazione pubblica e l'aggiunta di valori interi non sono cambiati nulla. – dbemerlin

0

Eccezione dice "chiavi devono essere stringhe o oggetto" in modo da provare

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

non ho la prova, però, solo una supposizione.

+0

Non sembra accettare tutti i tipi di oggetto, l'errore è sempre lo stesso. Grazie per il suggerimento però. – dbemerlin

0

Ho creato estensione JavaScriptSerializer DeserializeDictionary- vedere 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

Usa Newtonsoft (Newtonsoft.Json.dll) per serializzare l'oggetto Dictionary e sareste bene. È una libreria di terze parti famosa che dovresti scaricare e includere nel tuo progetto come riferimento.

Vedere il seguente esempio: [? Come faccio a convertire un dizionario per una stringa JSON in C#]

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

In questi giorni, anche Microsoft consiglia di utilizzare la libreria JSON Newtonsoft: https://msdn.microsoft.com/en-us/library/system.web.script.serialization. JavaScriptSerializer (v = vs.110) .aspx – Mr47