将JSON转换为具有泛型类型的列表



我得到了一个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装饰了接口,并在那里指定了自定义转换器
  • 我已经更改了Type1Type2类来实现这个接口:
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告诉我们,此转换可用于IDocuments
  • ReadJson基于";类型";字段
  • 实际的转换使用Populate而不是JsonCovert.Deserialize来避免无限递归

最后,用法很简单:

static void Main(string[] args)
{
var sampleJson = File.ReadAllText("sample.json");
var sample = JsonConvert.DeserializeObject<TopLevel>(sampleJson);
Console.ReadLine();
}

最新更新