我正在使用Harvest API,我正在尝试尽可能简单地自动映射实体,不幸的是,当我发出请求时,GET /projects它会产生如下结果:
[{
project: {
name: "Test"
}
},
{
project: {
name: "Test 2"
}]
Run Code Online (Sandbox Code Playgroud)
在RestSharp中,我无法直接执行此操作:
client.Execute<List<Project>>(request)
Run Code Online (Sandbox Code Playgroud)
因为它会寻找一个叫做的属性Project.所以我必须创建另一个具有该属性的类,并将其命名为:
client.Execute<List<ProjectContainer>>(request)
Run Code Online (Sandbox Code Playgroud)
我不想为每个实体创建一个"容器"类,所以我认为我找到了一个聪明的解决方案来创建一个我可以使用的类:
public class ListContainer<T> where T : IHarvestEntity
{
public T Item { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
但是,当然,反序列化器不知道它需要将实体名称(或"项目")映射到属性Item.在restsharp文档中,我发现我可以[DeserializeAs(Name = "CustomProperty")]用来告诉反序列化器哪个字段映射到这个属性.但是,属性只允许常量,这意味着我不能这样做:
[DeserializeAs(Name = typeof(T).FullName)]
public T Item { get; set; }
Run Code Online (Sandbox Code Playgroud)
有谁知道这个聪明的解决方案?所以我不必创建10个不同的容器类?
我建议你使用Jath的XPath等价物.使用Json.NET,您可以解析字符串并创建动态对象.
使用SelectToken,您可以查询值或使用Linq.
代码看起来像这样(我没有测试它):
// execute the request
RestResponse response = client.Execute(request);
var content = response.Content; // raw content as string
JObject o = JObject.Parse(content);
IList<string> projectNames = o.SelectToken("project").Select(s => (string)s.name).ToList();
Run Code Online (Sandbox Code Playgroud)
您可以根据需要对路径进行编码或配置路径.
---编辑---
这是我测试的一个例子,将json字符串转换为项目列表.
var projects = JArray.Parse(response.Content).Select(r => new Project(r["project"]["name"].Value<string>())).ToList();
Run Code Online (Sandbox Code Playgroud)
为了保持简单,您可以使用List<dynamic>单行按名称使用和访问属性。
var names = client.Execute<List<dynamic>>(request).Data.Select(
item => item["project"]["name"]).ToList(); // list of names
Run Code Online (Sandbox Code Playgroud)
如果这还不够,那么您可以即兴创作自己的映射器并提取例如Project实例的集合:
var projects = client.Execute<List<dynamic>>(request).Data.Select(
item => Map<Project>(item)).ToList(); // list of Project instances
Run Code Online (Sandbox Code Playgroud)
其中,Map方法可以是这样的
public T Map<T>(dynamic item) where T : class
{
// inline for clarity
var mappings = new Dictionary<Type,Func<dynamic,object>>
{
{ typeof(Project), map => new Project(map["project"]["name"]) }
};
return (T)mappings[typeof(T)].Invoke(item);
}
Run Code Online (Sandbox Code Playgroud)
给定Project定义为
public class Project
{
public Project(string name)
{
Name = name;
}
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7790 次 |
| 最近记录: |