C# 基于字典键的JSON推断类类型
我想反序列化C# 基于字典键的JSON推断类类型,c#,json,dictionary,serialization,json.net,C#,Json,Dictionary,Serialization,Json.net,我想反序列化词典AbstractDataObject是SomeClass1和SomeClass2继承自的抽象类。字典的键值(字符串)是类的名称: { "StoredData": { "SomeClass1": { "Foo": "Test" }, "SomeClass2": { "Bar": 123 } } } 这些类如下所示(简化): 公共类数据 { 公共字典存储数据{get;set;} } 公共抽象类AbstractDataO
词典
AbstractDataObject
是SomeClass1
和SomeClass2
继承自的抽象类。字典的键值(字符串)是类的名称:
{
"StoredData": {
"SomeClass1": {
"Foo": "Test"
},
"SomeClass2": {
"Bar": 123
}
}
}
这些类如下所示(简化):
公共类数据
{
公共字典存储数据{get;set;}
}
公共抽象类AbstractDataObject
{
}
公共类SomeClass1:AbstractDataObject
{
公共字符串Foo{get;set;}
}
公共类SomeClass2:AbstractDataObject
{
公共整型条{get;set;}
}
如何让Json.NET根据字典键推断类类型?我环顾四周,但不确定从何处开始实现此功能您可以制作一个自定义的
JsonConverter
来处理此问题:
public class CustomDictionaryConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Dictionary<string, AbstractDataObject>);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var dict = new Dictionary<string, AbstractDataObject>();
JObject jo = JObject.Load(reader);
foreach (JProperty prop in jo.Properties())
{
switch (prop.Name)
{
case "SomeClass1":
dict.Add("SomeClass1", prop.Value.ToObject<SomeClass1>(serializer));
break;
case "SomeClass2":
dict.Add("SomeClass2", prop.Value.ToObject<SomeClass2>(serializer));
break;
}
}
return dict;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
公共类CustomDictionaryConverter:JsonConverter
{
公共覆盖布尔CanConvert(类型objectType)
{
返回objectType==typeof(字典);
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
var dict=新字典();
JObject jo=JObject.Load(读卡器);
foreach(jo.Properties()中的JProperty属性)
{
开关(道具名称)
{
案例“SomeClass1”:
dict.Add(“SomeClass1”,prop.Value.ToObject(序列化程序));
打破
案例“SomeClass2”:
dict.Add(“SomeClass2”,prop.Value.ToObject(序列化程序));
打破
}
}
返回命令;
}
公共覆盖布尔可写
{
获取{return false;}
}
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
抛出新的NotImplementedException();
}
}
然后像这样使用它:
Data data = JsonConvert.DeserializeObject<Data>(json, new CustomDictionaryConverter());
Data Data=JsonConvert.DeserializeObject(json,新的CustomDictionaryConverter());
Fiddle:使用类型名是危险的,因为它破坏了序列化的典型目的,即允许完全解耦的客户端/服务器。有没有一种方法可以设计成显式契约?@SilasReinagel显式契约是什么意思?例如,对于特定的远程调用,在客户端代码中使用具体的数据对象。@SilasReinagel哦,这需要完全重写我当前的代码库:(还有什么方法可以实现我想要的功能吗?我不相信Json.NET中包含了这些功能。在反序列化之前,您必须自己创建一个层来确定类型。这不是很难做到,但可能会在项目的后续阶段给您带来一些麻烦。
Data data = JsonConvert.DeserializeObject<Data>(json, new CustomDictionaryConverter());