Проблемы с Json Serialize Dictionary <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
Мой тестовый файл:
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 для сериализации.
UPDATE:
Теперь я переключился на Dictionary<String, Int32>
, и он работает, но я надеюсь, что кто-то покажет решение, поскольку мне не очень нравится использовать строки вместо безопасного переименования типа.
Ответы
Ответ 1
Я знаю это поздно, но, возможно, кто-то еще сможет использовать его в будущем. Вы можете добиться того, что вам нужно, используя 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);
Ответ 2
Используйте Newtonsoft (Newtonsoft.Json.dll) для сериализации объекта Dictionary, и все будет в порядке. Это популярная сторонняя библиотека, которую вы должны скачать и включить в свой проект в качестве ссылки.
См. пример ниже:
var _validationInfos = new Dictionary<ImportField, ValidationInfo>();
var serializedData = JsonConvert.SerializeObject(_validationInfos);
Ответ 3
Я думаю, что у вас проблемы, потому что TestEnum
объявлен как private enum
. Попытайтесь пометить его как public enum
. Сериализатор должен иметь возможность находить ваше перечисление через отражение, чтобы сериализовать его.
Также в соответствии с Docs перечисления должны иметь целочисленные значения. Поэтому вы можете написать:
public enum TestEnum { A = 1, B = 2, C =3 }
Кроме того, в документах говорится, что это перечисление будет просто отображаться в соответствующее целочисленное значение во время сериализации. Таким образом, в зависимости от того, что вы делаете на другом конце, String
может быть более выразительным и легче работать.
Ответ 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
Ive создал расширение 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;
}