我正在使用Harvest API,我尝试尽可能简单地自动映射实体,不幸的是,当我执行GET /projects
之类的请求时,它会生成如下结果:
[{
project: {
name: "Test"
}
},
{
project: {
name: "Test 2"
}]
在RestSharp中,我不能直接这样做:
client.Execute<List<Project>>(request)
因为它将寻找名为Project
的属性。所以我必须创建另一个具有该属性的类,并将其命名为:
client.Execute<List<ProjectContainer>>(request)
我不想制作一个容器&#39;每个实体的类,所以我认为我找到了一个聪明的解决方案,可以创建一个我可以使用的类:
public class ListContainer<T> where T : IHarvestEntity
{
public T Item { get; set; }
}
但是,当然,反序列化器不知道它需要将实体名称(或&#34; Project&#34;)映射到属性Item
。在restsharp文档中,我发现我可以使用[DeserializeAs(Name = "CustomProperty")]
告诉反序列化器哪个字段映射到此属性。但是,属性只允许常量,这意味着我无法做到:
[DeserializeAs(Name = typeof(T).FullName)]
public T Item { get; set; }
有谁知道这个聪明的解决方案?所以我不必创建10个不同的容器类?
答案 0 :(得分:8)
我建议你使用Jath的XPath等价物。使用Json.NET,您可以parse字符串并创建动态对象。
使用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();
您可以根据自己的喜好对路径进行编码或配置路径。
---编辑---
这是我测试的一个例子,将json字符串转换为项目列表。
var projects = JArray.Parse(response.Content).Select(r => new Project(r["project"]["name"].Value<string>())).ToList();
答案 1 :(得分:3)
为了保持简单,您可以使用List<dynamic>
并使用单行按名称访问属性/属性。
var names = client.Execute<List<dynamic>>(request).Data.Select(
item => item["project"]["name"]).ToList(); // list of names
如果这还不够,那么您可以即兴创作自己的映射器并提取例如Project
个实例:
var projects = client.Execute<List<dynamic>>(request).Data.Select(
item => Map<Project>(item)).ToList(); // list of Project instances
其中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);
}
给定Project
定义为
public class Project
{
public Project(string name)
{
Name = name;
}
public string Name { get; set; }
}