C# 使用.NET 4.0任务模式使用HTTPClient.ReadAsAsync将JSON反序列化为数组或列表
我正在尝试反序列化从C# 使用.NET 4.0任务模式使用HTTPClient.ReadAsAsync将JSON反序列化为数组或列表,c#,json,asp.net-mvc-4,task-parallel-library,dotnet-httpclient,C#,Json,Asp.net Mvc 4,Task Parallel Library,Dotnet Httpclient,我正在尝试反序列化从http://api.usa.gov/jobs/search.json?query=nursing+作业使用.NET 4.0任务模式。它返回这个JSON('加载JSON数据'@http://jsonviewer.stack.hu/) 索引操作: public class HomeController : Controller { public ActionResult Index() { Jobs model = null; v
http://api.usa.gov/jobs/search.json?query=nursing+作业
使用.NET 4.0任务模式。它返回这个JSON('加载JSON数据'@http://jsonviewer.stack.hu/
)
索引操作:
public class HomeController : Controller
{
public ActionResult Index()
{
Jobs model = null;
var client = new HttpClient();
var task = client.GetAsync("http://api.usa.gov/jobs/search.json?query=nursing+jobs")
.ContinueWith((taskwithresponse) =>
{
var response = taskwithresponse.Result;
var jsonTask = response.Content.ReadAsAsync<Jobs>();
jsonTask.Wait();
model = jsonTask.Result;
});
task.Wait();
...
}
如何使用.NET4.0任务模式处理此站点的JSON?在进入.NET4.5中的await async
模式之前,我想让它工作起来
答案更新:
下面是一个使用.NET4.5AsyncWait模式和Brumcouse答案的示例
public async Task<ActionResult>Index()
{
List<Job> model = null;
var client = newHttpClient();
// .NET 4.5 async await pattern
var task = await client.GetAsync(http://api.usa.gov/jobs/search.json?query=nursing+jobs);
var jsonString = await task.Content.ReadAsStringAsync();
model = JsonConvert.DeserializeObject<List<Job>>(jsonString);
returnView(model);
}
公共异步任务索引()
{
列表模型=null;
var client=newHttpClient();
//.NET 4.5异步等待模式
var task=await client.GetAsync(http://api.usa.gov/jobs/search.json?query=nursing+工作);
var jsonString=await task.Content.ReadAsStringAsync();
model=JsonConvert.DeserializeObject(jsonString);
返回视图(模型);
}
您需要引入System.Threading.Tasks
命名空间。注意:在
.Content
上没有可用的.ReadAsString
方法,这就是我使用.ReadAsStringAsync
方法的原因。尝试使用类似Json2csharp.com的网站,而不是手动启动模型。粘贴一个示例JSON响应,越完整越好,然后拉入生成的类。这至少可以去掉一些移动的部分,让您在csharp中看到JSON的形状,让序列化程序更容易,而且您不必添加属性
只要让它工作起来,然后对类名进行修改,以符合命名约定,并在以后添加属性
编辑:
好了,在稍微搞乱之后,我已经成功地将结果反序列化到作业列表中(我使用Json2csharp.com为我创建了这个类)
公共类作业
{
公共字符串id{get;set;}
公共字符串位置_title{get;set;}
公共字符串组织_name{get;set;}
公共字符串速率\u间隔\u代码{get;set;}
公共整数最小值{get;set;}
公共整数最大值{get;set;}
公共字符串开始日期{get;set;}
公共字符串结束日期{get;set;}
公共列表位置{get;set;}
公共字符串url{get;set;}
}
并编辑您的代码:
List<Job> model = null;
var client = new HttpClient();
var task = client.GetAsync("http://api.usa.gov/jobs/search.json?query=nursing+jobs")
.ContinueWith((taskwithresponse) =>
{
var response = taskwithresponse.Result;
var jsonString = response.Content.ReadAsStringAsync();
jsonString.Wait();
model = JsonConvert.DeserializeObject<List<Job>>(jsonString.Result);
});
task.Wait();
列表模型=null;
var client=新的HttpClient();
var task=client.GetAsync(“http://api.usa.gov/jobs/search.json?query=nursing+工作“)
.继续((带响应的任务)=>
{
var response=taskwithresponse.Result;
var jsonString=response.Content.ReadAsStringAsync();
jsonString.Wait();
model=JsonConvert.DeserializeObject(jsonString.Result);
});
task.Wait();
这意味着您可以摆脱包含对象。值得注意的是,这不是一个与任务相关的问题,而是一个反序列化问题
编辑2:
有一种方法可以在VisualStudio中获取JSON对象并生成类。只需复制所选的JSON,然后编辑>粘贴特殊>将JSON粘贴为类。这里用了整整一页来讨论这一点:
var response=taskwithresponse.Result;
var jsonString=response.ReadAsAsync().Result;
返回类型取决于服务器,有时响应实际上是一个JSON数组,但以文本/普通格式发送
在请求中设置accept标头应获得正确的类型:
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
然后可以将其序列化为JSON列表或数组。
感谢@svick的评论,这让我很好奇它是否会起作用
我在没有配置accept标头的情况下得到的异常是System.Net.Http.UnsupportedMediaTypeException
以下代码比较干净,应该可以工作(未经测试,但在我的情况下可以工作):
var-client=new-HttpClient();
client.DefaultRequestHeaders.Accept.Add(新的MediaTypeWithQualityHeaderValue(“应用程序/json”);
var response=wait client.GetAsync(“http://api.usa.gov/jobs/search.json?query=nursing+工作);;
var model=await response.Content.ReadAsAsync();
您是否尝试过ReadAsAsync()
?不起作用,在taskwithresponse的.Result上产生此错误。错误1“System.Threading.Tasks.Task”不包含“Result”的定义,并且找不到接受类型为“System.Threading.Tasks.Task”的第一个参数的扩展方法“Result”(是否缺少using指令或程序集引用?),这没有任何意义,请在ReadAsAsync()中更改类型
无法在代码运行之前更改代码的方式。它确实做到了。它嵌入在ContinueWith语句中。请创建一个新的MVC4应用程序(在VS 2012中工作)并粘贴到此控制器和两个类?你能重复这个错误吗?如果是这样的话,你能建议一个经过测试的解决方案来解决这个问题吗?我使用Fiddler来发现JSON,它显示返回了多个{}。Json2csharp.com是一个很好的工具,但它没有显示有多个{}。我已经成功地将JsonProperty属性用于其他URL,因此我的问题不在于JsonProperty属性,而在于如何使用.NET 4.0中的任务模式将返回的JSON反序列化到数组或列表中。是的,正如我从一开始就说过的,这是一个JSON反序列化问题。捕获字符串,然后JSONVERTING完成了这个技巧,现在它可以工作了。无需修改作业类型,我使用JsonProperty属性保留了我的原始作业类型。如果您只想同步而不等待它们完成,那么使用异步方法获取数据是没有意义的。如果您只是要同步等待,那么最好从一开始就使用同步方法。如果你是
public async Task<ActionResult>Index()
{
List<Job> model = null;
var client = newHttpClient();
// .NET 4.5 async await pattern
var task = await client.GetAsync(http://api.usa.gov/jobs/search.json?query=nursing+jobs);
var jsonString = await task.Content.ReadAsStringAsync();
model = JsonConvert.DeserializeObject<List<Job>>(jsonString);
returnView(model);
}
public class Job
{
public string id { get; set; }
public string position_title { get; set; }
public string organization_name { get; set; }
public string rate_interval_code { get; set; }
public int minimum { get; set; }
public int maximum { get; set; }
public string start_date { get; set; }
public string end_date { get; set; }
public List<string> locations { get; set; }
public string url { get; set; }
}
List<Job> model = null;
var client = new HttpClient();
var task = client.GetAsync("http://api.usa.gov/jobs/search.json?query=nursing+jobs")
.ContinueWith((taskwithresponse) =>
{
var response = taskwithresponse.Result;
var jsonString = response.Content.ReadAsStringAsync();
jsonString.Wait();
model = JsonConvert.DeserializeObject<List<Job>>(jsonString.Result);
});
task.Wait();
var response = taskwithresponse.Result;
var jsonString = response.ReadAsAsync<List<Job>>().Result;
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("http://api.usa.gov/jobs/search.json?query=nursing+jobs");
var model = await response.Content.ReadAsAsync<List<Job>>();