Json序列化字典的问题<enum,int32 =“”> </enum,>

时间:2010-05-23 18:27:57

标签: c# json serialization dictionary

每当我尝试序列化字典时,我都会得到例外:

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

我的测试用例是:

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
  }

}

当我在词典中输入内容时,我可以使用.ToString(),但由于它在性能相关方法中经常使用,我更喜欢使用枚举。

我唯一的解决方案是在进入性能关键区域之前使用.ToString()和转换,但这很笨拙,我必须更改我的代码结构才能序列化数据。

有没有人知道如何将字典序列化为<Enum, Int32>

我使用System.Web.Script.Serialization.JavaScriptSerializer进行序列化。

更新

我现在切换到Dictionary<String, Int32>并且它有效,但我希望有人会显示解决方案,因为我不喜欢使用字符串代替类型安全枚举。

5 个答案:

答案 0 :(得分:18)

我知道现在已经很晚了,但也许其他人可以在将来使用它。您可以使用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);

答案 1 :(得分:5)

使用Newtonsoft(Newtonsoft.Json.dll)序列化Dictionary对象,你会没事的。这是一个受欢迎的第三方库,您必须下载并包含在您的项目中作为参考。

见下面的例子:

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

答案 2 :(得分:0)

我认为您遇到了麻烦,因为TestEnum被声明为private enum。尝试将其标记为public enum。序列化程序需要能够通过反射找到你的枚举,以便序列化它。

同样根据Docs,枚举必须具有整数值。所以你可能想写:

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

此外,文档说这个枚举只会在序列化过程中映射到相应的整数值。因此,根据您在另一端所做的事情,String可能更具表现力,更易于使用。

答案 3 :(得分:0)

异常说“键必须是字符串或对象”,所以请尝试

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

我没有测试它,只是一个猜测。

答案 4 :(得分:0)

我已经创建了JavaScriptSerializer扩展DeserializeDictionary-请参阅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;
}