我有一个JSON:
{
"data": { "A": 5, "B": 6 },
"foo": "foo",
"bar": "bar"
}
我需要将数据反序列化为类:
public Dictionary<MyEnum, int> Data { get; set; }
public string Foo { get; set; }
public string Bar { get; set; }
但MyEnum值分别为CodeA
和CodeB
,而不仅仅是A
和B
。
我有一个可以处理转换的自定义转换器。但是如何指定JsonConverter
与词典键一起使用?
答案 0 :(得分:13)
我认为唯一的方法是为整个Dictionary<MyEnum, int>
类型或Dictionary<MyEnum, T>
创建一个JsonConverter。
字典键不被视为值,不会通过JsonConverters运行。 TypeConverters本来就是一个解决方案,但枚举转换的默认字符串将在它查看TypeConverters之前输入。
所以...我认为不能以任何其他方式完成。
编辑:
没有经过全面测试,但我在我的项目中使用了类似的东西:
public class DictionaryWithSpecialEnumKeyConverter : JsonConverter
{
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotSupportedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var valueType = objectType.GetGenericArguments()[1];
var intermediateDictionaryType = typeof(Dictionary<,>).MakeGenericType(typeof(string), valueType);
var intermediateDictionary = (IDictionary)Activator.CreateInstance(intermediateDictionaryType);
serializer.Populate(reader, intermediateDictionary);
var finalDictionary = (IDictionary)Activator.CreateInstance(objectType);
foreach (DictionaryEntry pair in intermediateDictionary)
finalDictionary.Add(Enum.Parse(MyEnum, "Code" + pair.Key, false), pair.Value);
return finalDictionary;
}
public override bool CanConvert(Type objectType)
{
return objectType.IsA(typeof(IDictionary<,>)) &&
objectType.GetGenericArguments()[0].IsA<MyEnum>();
}
}
你需要这个小帮手:
public static bool IsA(this Type type, Type typeToBe)
{
if (!typeToBe.IsGenericTypeDefinition)
return typeToBe.IsAssignableFrom(type);
var toCheckTypes = new List<Type> { type };
if (typeToBe.IsInterface)
toCheckTypes.AddRange(type.GetInterfaces());
var basedOn = type;
while (basedOn.BaseType != null)
{
toCheckTypes.Add(basedOn.BaseType);
basedOn = basedOn.BaseType;
}
return toCheckTypes.Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeToBe);
}
希望它适合你。
答案 1 :(得分:0)
以下是使用json和Dictionary以及任何类型的键的问题的通用解决方案:
[JsonObject]
public class MyKeyValuePair<TKey, TValue>
{
public TKey MyKey;
public TValue MyValue;
[JsonConstructor]
public MyKeyValuePair()
{
}
public MyKeyValuePair(TKey t1, TValue t2)
{
MyKey = t1;
MyValue = t2;
}
}
[JsonObject]
public class MyDictionaty<TKey, TValue>
{
public ICollection<MyKeyValuePair<TKey, TValue>> Collection;
[JsonConstructor]
public MyDictionaty()
{
}
public MyDictionaty(Dictionary<TKey, TValue> refund)
{
Collection = BuildMyKeyValuePairCollection(refund);
}
internal Dictionary<TKey, TValue> ToDictionary()
{
return Collection.ToDictionary(pair => pair.MyKey, pair => pair.MyValue);
}
private ICollection<MyKeyValuePair<TKey, TValue>> BuildMyKeyValuePairCollection(Dictionary<TKey, TValue> refund)
{
return refund.Select(o => new MyKeyValuePair<TKey, TValue>(o.Key, o.Value)).ToList();
}
}
[JsonObject]
public class ClassWithDictionary
{
[JsonProperty]
private readonly MyDictionary<AnyKey, AnyValue> _myDictionary;
private Dictionary<AnyKey, AnyValue> _dic;
[JsonConstructor]
public ClassWithDictionary()
{
}
public ClassWithDictionary(Dictionary<AnyKey, AnyValue> dic)
{
_dic= dic;
_myDictionary = new MyDictionaty<AnyKey, AnyValue>(dic);
}
public Dictionary<AnyKey, AnyValue> GetTheDictionary()
{
_dic = _dic??_myDictionary.ToDictionary();
return _dic;
}
}
答案 2 :(得分:0)
我无法使用任何TypeConverter解决方案,也不想拥有一个JsonConverter来构建一个字符串字典,然后将所有内容复制到一个新字典中,所以我采用了这样的方法:
public sealed class MyEnumKeyDictionary<TValue> : IReadOnlyDictionary<MyEnum, TValue>, IDictionary<string, TValue>
{
private readonly Dictionary<MyEnum, TValue> actual = new Dictionary<MyEnum, TValue>();
// implement IReadOnlyDictionary implicitly, passing everything from `actual`
// implement IDictionary explicitly, passing everything into/from `actual` after doing Enum.Parse/Enum.ToString
}