2010-05-23 28 views
12

bất cứ khi nào tôi cố gắng để serialize điển tôi nhận được ngoại lệ:Vấn đề với Json Serialize điển <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 

My testcase là:

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 
    } 

} 

Dĩ nhiên tôi có thể sử dụng ToString() bất cứ khi nào tôi nhập một cái gì đó vào từ điển nhưng kể từ khi nó được sử dụng khá thường xuyên trong các phương pháp hiệu suất có liên quan tôi muốn sử dụng enum.

Giải pháp duy nhất của tôi là sử dụng. ToString() và chuyển đổi trước khi vào khu vực quan trọng hiệu suất nhưng đó là vụng về và tôi sẽ phải thay đổi cấu trúc mã của mình chỉ để có thể tuần tự hóa dữ liệu.

Có ai có ý tưởng làm cách nào tôi có thể tuần tự hóa từ điển là <Enum, Int32> không?

Tôi sử dụng System.Web.Script.Serialization.JavaScriptSerializer để tuần tự hóa.

UPDATE:

Tôi chuyển sang Dictionary<String, Int32> bây giờ và nó hoạt động nhưng tôi hy vọng ai đó cho thấy một giải pháp như tôi không thực sự thích sử dụng chuỗi ở vị trí của một kiểu enum an toàn.

+0

thể trùng lặp của (http: // stackoverflow.com/questions/5597349/how-do-i-convert-a-dictionary-to-a-json-string-in-c) –

Trả lời

18

Tôi biết đó là muộn, nhưng có lẽ người khác có thể tận dụng nó trong tương lai. Bạn có thể đạt được những gì bạn cần bằng cách sử dụng 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

Không quá muộn ... Vẫn hữu ích trong năm 2016 –

+0

Tôi vẫn khuyên bạn nên sử dụng Json.NET như nó nêu trong tài liệu lớp JavaScriptSerializer: https://msdn.microsoft.com/en-us/library/system.web.script .serialization.javascriptserializer (v = vs.110) .aspx – kimbaudi

0

Tôi nghĩ rằng bạn đang gặp sự cố vì TestEnum được khai báo là private enum. Hãy thử đánh dấu nó là public enum. Trình serializer cần có khả năng tìm enum của bạn thông qua sự phản chiếu để sắp xếp nó.

Cũng theo Docs, các enums phải có giá trị số nguyên. Vì vậy, bạn có thể muốn viết:

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

Ngoài ra, các tài liệu nói rằng enum này sẽ chỉ được ánh xạ đến giá trị nguyên tương ứng trong quá trình tuần tự hóa. Vì vậy, tùy thuộc vào những gì bạn đang làm ở đầu bên kia, String s có thể mang tính biểu cảm và dễ làm việc hơn.

+0

Cảm ơn gợi ý, nhưng thay đổi enum thành công khai và thêm các giá trị nguyên không thay đổi bất cứ điều gì. – dbemerlin

0

ngoại lệ nói "chìa khóa phải là các chuỗi hoặc đối tượng" vì vậy hãy thử

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

tôi không kiểm tra nó, mặc dù chỉ là một phỏng đoán.

+0

Dường như không chấp nhận tất cả các loại đối tượng, lỗi vẫn như cũ. Nhờ đề nghị mặc dù. – dbemerlin

0

tôi đã tạo ra phần mở rộng JavaScriptSerializer DeserializeDictionary- thấy 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

Sử dụng Newtonsoft (Newtonsoft.Json.dll) để tuần tự hóa đối tượng từ điển và bạn sẽ ổn. Đó là một thư viện bên thứ ba phổ biến mà bạn sẽ phải tải xuống và đưa vào dự án của bạn làm tài liệu tham khảo.

Xem ví dụ dưới đây: [? Làm thế nào để chuyển đổi một từ điển để một JSON String trong C#]

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

Những ngày này, thậm chí Microsoft khuyên bạn nên sử dụng thư viện JSON Newtonsoft: https://msdn.microsoft.com/en-us/library/system.web.script.serialization. javascriptserializer (v = vs.110) .aspx – Mr47

Các vấn đề liên quan