如何使用ReadAsAsync< T>这个数据架构? [英] How can I use ReadAsAsync<T> with this data schema?
问题描述
我使用System.Net.Http.HttpClient,中的NuGet 目前可用的版本,
在JSON格式的服务中检索数据。数据大致是这样的:
I am using System.Net.Http.HttpClient, the version currently available in NuGet, to retrieve data from a service in json format. The data roughly looks like this:
{
"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字符串对象图。该类型定义看起来大致是这样的:
I use HttpContentExtensions.ReadAsAsync<T>
to de-serialize that json string into an object graph. The type definitions looks roughly like this:
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; }
}
下面的问题:我想要的物品的类型孩子
来取决于样
属性各不相同。如果样
是TYPE1,那么我要反序列化的......让我们叫它类型1
的对象。如果样
是3型,那么我想类型的对象的Type3
。
Here's the problem: I desire the type of the items in children
to vary depending on the kind
property. If kind
is "type1" then I want to de-serialize an object of... let's call it Type1
. If kind
is "type3" then I want an object of type Type3
.
现在,我可以反序列化列表<类型1>
或列表< 3类> ;
,但我不知道该怎么告诉反序列化逻辑两者区分开来。
Right now, I can deserialize a List<Type1>
or a List<Type3>
, but I don't know how to tell the de-serialization logic to distinguish between the two.
我可以合并TYPE1数据对象和类型3的数据的所有属性对象到一个单一的.NET类型。但属性的数量足够大,这就会变得混乱。
I could merge all the properties of the "type1" data object and the "type3" data object into a single .NET Type. But the number of properties is large enough that this gets messy.
如果在JSON的属性的名称(在这种情况下,数据
)是不同的,我可以区分使用那。如果,例如,数据是这样的:
If the name of the property in the JSON (in this case data
) were different, I could distinguish using that. If, for example, the data looked like this:
"children": [{
"kind": "type1",
"t1data": { ... }
}, {
"kind": "type3",
"t3data": { ... }
}]
......然后我可以做这样的事情在.NET:
...then I could do something like this in .NET:
public class OneItem
{
public string kind { get;set; }
public Type1 t1data { get;set; }
public Type3 t3data { get;set; }
}
但我的数据模式并没有像她那样。
But my data schema doesn't look like that.
是否有可能选择由数据的内容进行解串行化的类型?换句话说,
看一个属性的值(在这种情况下,样
),以确定如何反序列为另一个属性内容(在此情况下,数据
)。
Is it possible to choose the type for de-serialization by the content of the data? In other words,
look at the value of one property (in this case, kind
) to determine how to de-serialize the content for another property (in this case, data
).
或者是有可能注入的过滤器或变压器作用于JSON ReadAsAsync前试图反序列化呢?
Or is it possible to inject a filter or transformer that acts on the JSON before ReadAsAsync tries to deserialize it?
如果是这样,怎么样?
If so, How?
推荐答案
如果你真行瓦特/你的反应做一些预处理,你可以使用Json.NET,你应该。可以做你想做的。
If you're ok w/ doing some pre-processing on your response and you can use Json.NET, you should be able to do what you want.
由于以下类:
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)));
}
写到控制台输出是:
The output written to the console is:
{
"$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的预期格式,这将正常工作。
So if you can transform your received response to match that of Json.NET's expected format, this will work.
要拼凑这一切在一起,你就需要编写自定义MediaTypeFormatter,并把它传递给ReadAsAsync<>()调用
To piece all of this together, you would need to write a custom MediaTypeFormatter and pass it to the ReadAsAsync<>() call.
这篇关于如何使用ReadAsAsync< T>这个数据架构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!