json.net:为字典键指定转换器
我有一个JSON:
{ "data": { "A": 5, "B": 6 }, "foo": "foo", "bar": "bar" }
我需要将数据反序列化为一个类:
public Dictionary Data { get; set; } public string Foo { get; set; } public string Bar { get; set; }
但MyEnum值分别是CodeA
和CodeB
而不是简单的A
和B
我有一个可以处理转换的自定义转换器。 但是如何指定JsonConverter
与Dictionary键一起使用?
我相信唯一的方法是为整个Dictionary
类型或Dictionary
创建一个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(); } }
你需要这个小帮手:
public static bool IsA(this Type type, Type typeToBe) { if (!typeToBe.IsGenericTypeDefinition) return typeToBe.IsAssignableFrom(type); var toCheckTypes = new List { 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); }
希望它对你有帮助。
以下是使用json和Dictionary以及任何类型的键的问题的通用解决方案:
[JsonObject] public class MyKeyValuePair { public TKey MyKey; public TValue MyValue; [JsonConstructor] public MyKeyValuePair() { } public MyKeyValuePair(TKey t1, TValue t2) { MyKey = t1; MyValue = t2; } } [JsonObject] public class MyDictionaty { public ICollection> Collection; [JsonConstructor] public MyDictionaty() { } public MyDictionaty(Dictionary refund) { Collection = BuildMyKeyValuePairCollection(refund); } internal Dictionary ToDictionary() { return Collection.ToDictionary(pair => pair.MyKey, pair => pair.MyValue); } private ICollection> BuildMyKeyValuePairCollection(Dictionary refund) { return refund.Select(o => new MyKeyValuePair(o.Key, o.Value)).ToList(); } } [JsonObject] public class ClassWithDictionary { [JsonProperty] private readonly MyDictionary _myDictionary; private Dictionary _dic; [JsonConstructor] public ClassWithDictionary() { } public ClassWithDictionary(Dictionary dic) { _dic= dic; _myDictionary = new MyDictionaty(dic); } public Dictionary GetTheDictionary() { _dic = _dic??_myDictionary.ToDictionary(); return _dic; } }