如何将 ReadAsAsync 与此数据架构一起使用
本文关键字:数据 一起 ReadAsAsync | 更新日期: 2023-09-27 18:33:08
我正在使用System.Net.Http.HttpClient,NuGet中当前可用的版本,以 JSON 格式从服务中检索数据。数据大致如下所示:
{
"schema": "Listing",
"data": {
"key": "28ba648c-de24-45d4-a7d9-70f810cf5438",
"children": [{
"kind": "type1",
"data": {
"body": "Four score and seven years ago...",
"parent_id": "2qh3l",
"report_count": 0,
"name": "c4j6yeh"
}
}, {
"kind": "type3",
"data": {
"domain": "abc.def.com",
"flagged": true,
"category": "news",
"saved": false,
"id": "t3dz0",
"created": 1335998011.0
}
}]
}
}
我使用 HttpContentExtensions.ReadAsAsync<T>
将该 json 字符串反序列化为对象图。 类型定义大致如下所示:
public class Response
{
public String schema { get;set; }
public ListingData data { get;set; }
}
public class ListingData
{
public string key { get;set; }
public List<OneItem> children { get;set; }
}
问题是:我希望children
中的项目类型根据kind
属性而有所不同。 如果kind
是"type1",那么我想反序列化一个对象...让我们称之为Type1
. 如果kind
是"type3",那么我想要一个类型为 Type3
的对象。
现在,我可以反序列化List<Type1>
或List<Type3>
,但我不知道如何告诉反序列化逻辑来区分两者。
我可以将"type1"数据对象和"type3"数据对象的所有属性合并到单个 .NET 类型中。 但是属性的数量足够大,以至于这变得混乱。
如果 JSON 中的属性名称(在本例中为 data
(不同,我可以使用它进行区分。 例如,如果数据如下所示:
"children": [{
"kind": "type1",
"t1data": { ... }
}, {
"kind": "type3",
"t3data": { ... }
}]
。然后我可以在 .NET 中做这样的事情:
public class OneItem
{
public string kind { get;set; }
public Type1 t1data { get;set; }
public Type3 t3data { get;set; }
}
但我的数据架构看起来不像那样。
是否可以根据数据内容选择反序列化的类型? 换句话说,查看一个属性的值(在本例中为 kind
(,以确定如何反序列化另一个属性(在本例中为 data
(的内容。
或者是否可以在 ReadAsAsync 尝试反序列化之前注入作用于 JSON 的筛选器或转换器?
如果是这样,如何?
如果你对你的响应进行一些预处理并且你可以使用 Json.NET,你应该能够做你想做的事。
给定以下类:
public class Response
{
public string schema
{
get;
set;
}
public ListingData data
{
get;
set;
}
}
public class ListingData
{
public string key
{
get;
set;
}
public List<object> children
{
get;
set;
}
}
public class Type1
{
public string body
{
get;
set;
}
public string parent_id
{
get;
set;
}
public int report_count
{
get;
set;
}
public string name
{
get;
set;
}
}
public class Type3
{
public string domain
{
get;
set;
}
public bool flagged
{
get;
set;
}
public string category
{
get;
set;
}
public bool saved
{
get;
set;
}
public string id
{
get;
set;
}
public double created
{
get;
set;
}
}
此测试通过:
[Test]
public void RoundTrip()
{
var response = new Response
{
schema = "Listing",
data = new ListingData
{
key = "28ba648c-de24-45d4-a7d9-70f810cf5438",
children = new List<object>
{
new Type1
{
body = "Four score and seven years ago...",
parent_id = "2qh3l",
report_count = 0,
name = "c4j6yeh"
},
new Type3
{
domain = "abc.def.com",
flagged = true,
category = "news",
saved = false,
id = "t3dz0",
created = 1335998011.0
}
}
}
};
var jsonSerializerSettings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
TypeNameHandling = TypeNameHandling.Objects
};
string serializedResponse = JsonConvert.SerializeObject(response, jsonSerializerSettings);
Console.WriteLine(serializedResponse);
var roundTrippedResponse = JsonConvert.DeserializeObject<Response>(serializedResponse, jsonSerializerSettings);
Assert.That(roundTrippedResponse.data.children.First().GetType(), Is.EqualTo(typeof(Type1)));
Assert.That(roundTrippedResponse.data.children.Last().GetType(), Is.EqualTo(typeof(Type3)));
}
写入控制台的输出为:
{
"$type": "Test.Response, Test",
"schema": "Listing",
"data": {
"$type": "Test.ListingData, Test",
"key": "28ba648c-de24-45d4-a7d9-70f810cf5438",
"children": [
{
"$type": "Test.Type1, Test",
"body": "Four score and seven years ago...",
"parent_id": "2qh3l",
"report_count": 0,
"name": "c4j6yeh"
},
{
"$type": "Test.Type3, Test",
"domain": "abc.def.com",
"flagged": true,
"category": "news",
"saved": false,
"id": "t3dz0",
"created": 1335998011.0
}
]
}
}
因此,如果可以转换收到的响应以匹配 Json.NET 的预期格式,这将起作用。
要将所有这些拼凑在一起,您需要编写一个自定义的 MediaTypeFormatter 并将其传递给 ReadAsAsync<>(( 调用。