我得到了一个JSON响应,如:
{
"items": [
{
"document": {
"id": "123",
"title": "title2",
"description": "Description1",
"type": "Typ1"
}
},
{
"document": {
"id": "456",
"title": "title2",
"description": "desctiption2",
"type": "Type2",
"Type2Property": "Type2Property"
}
}
]
}
正如您在上面看到的,我有两个具有不同属性的值(仅作为示例(。在我的代码中,我有两个类。
public class Type1
{
public string Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Type { get; set; }
}
public class Type2
{
public string Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Type { get; set; }
public string Type2Property {get; set;}
}
问题:如何创建一个将Type1和Type2组合在一起的泛型列表。将来,我可以拥有更多的TypeX(具有不同的属性(。因此,我想将JSON解析为一个通用列表。
更新:我可以通过json中的Type属性过滤json。
解决此问题的一种方法是创建自定义JsonConverter
并覆盖其ReadJson
方法。
我引入了几个助手类来解析整个示例json:
public class TopLevel
{
public MidLevel[] Items { get; set; }
}
public class MidLevel
{
public IDocument Document { get; set; }
}
[JsonConverter(typeof(DocumentTypeConverter))]
public interface IDocument
{
}
- 我已经创建了一个
IDocument
标记接口。如果您愿意,可以使用abstract class
- 我已经用
JsonConverterAttribute
装饰了接口,并在那里指定了自定义转换器 - 我已经更改了
Type1
和Type2
类来实现这个接口:
public class Type1 : IDocument
{
...
public string Type { get; set; }
}
public class Type2 : IDocument
{
...
public string Type { get; set; }
public string Type2Property { get; set; }
}
DocumentTypeConverter
的天真实现看起来是这样的:
(显然,您可以使类型更安全(
public class DocumentTypeConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
=> throw new NotImplementedException();
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
switch (jObject["type"].Value<string>())
{
case "Typ1":
{
var obj = new Type1();
serializer.Populate(jObject.CreateReader(), obj);
return obj;
}
case "Type2":
{
var obj = new Type2();
serializer.Populate(jObject.CreateReader(), obj);
return obj;
}
default:
throw new Exception();
}
}
public override bool CanConvert(Type objectType)
=> objectType == typeof(IDocument);
}
CanConvert
告诉我们,此转换可用于IDocument
s- ReadJson基于";类型";字段
- 实际的转换使用
Populate
而不是JsonCovert.Deserialize
来避免无限递归
最后,用法很简单:
static void Main(string[] args)
{
var sampleJson = File.ReadAllText("sample.json");
var sample = JsonConvert.DeserializeObject<TopLevel>(sampleJson);
Console.ReadLine();
}