【问题标题】:Problems with Json Serialize Dictionary<Enum, Int32>Json 序列化字典的问题<Enum, Int32>
【发布时间】:2011-02-22 23:44:09
【问题描述】:

每当我尝试序列化字典时,我都会遇到异常:

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() 并在进入性能关键区域之前进行转换,但这很笨拙,我必须更改我的代码结构才能序列化数据。

有谁知道我如何将字典序列化为&lt;Enum, Int32&gt;

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

更新:

我现在切换到 Dictionary&lt;String, Int32&gt; 并且它可以工作,但我希望有人提出解决方案,因为我不太喜欢使用字符串来代替类型安全的枚举。

【问题讨论】:

标签: c# json serialization dictionary


【解决方案1】:

使用 Newtonsoft (Newtonsoft.Json.dll) 序列化 Dictionary 对象就可以了。这是一个流行的第三方库,您必须下载并包含在您的项目中作为参考。

请看下面的例子:

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

【讨论】:

【解决方案2】:

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

【讨论】:

【解决方案3】:

我已经创建了 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;
}

【讨论】:

    【解决方案4】:

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

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

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

    【讨论】:

    • 它似乎不接受所有对象类型,错误仍然相同。不过感谢您的建议。
    【解决方案5】:

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

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

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

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

    【讨论】:

    • 感谢您的建议,但将枚举更改为公共并添加整数值并没有改变任何内容。
    猜你喜欢
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-08
    • 2017-05-17
    • 1970-01-01
    相关资源
    最近更新 更多