使用.net 4.0任务模式,使用HTTPClient . readasasync将JSON反序列化为数组或列表

本文关键字:使用 反序列化 JSON 数组 列表 HTTPClient net 任务 模式 readasasync | 更新日期: 2023-09-27 18:08:04

我正在尝试使用。net 4.0任务模式反序列化从http://api.usa.gov/jobs/search.json?query=nursing+jobs返回的JSON。它返回这个JSON ('Load JSON data' @ http://jsonviewer.stack.hu/)。

[
  {
    "id": "usajobs:353400300",
    "position_title": "Nurse",
    "organization_name": "Indian Health Service",
    "rate_interval_code": "PA",
    "minimum": 42492,
    "maximum": 61171,
    "start_date": "2013-10-01",
    "end_date": "2014-09-30",
    "locations": [
      "Gallup, NM"
    ],
    "url": "https://www.usajobs.gov/GetJob/ViewDetails/353400300"
  },
  {
    "id": "usajobs:359509200",
    "position_title": "Nurse",
    "organization_name": "Indian Health Service",
    "rate_interval_code": "PA",
    "minimum": 42913,
    "maximum": 61775,
    "start_date": "2014-01-16",
    "end_date": "2014-12-31",
    "locations": [
      "Gallup, NM"
    ],
    "url": "https://www.usajobs.gov/GetJob/ViewDetails/359509200"
  },
  ...
]

指数行动:

  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();
      ...
     }

Job和Job类:

  [JsonArray]
  public class Jobs { public List<Job> JSON; }
  public class Job
  {
    [JsonProperty("organization_name")]
    public string Organization { get; set; }
    [JsonProperty("position_title")]
    public string Title { get; set; }
  }

当我在jsonTask.Wait();上设置断点并检查jsonTask时,状态为指责。InnerException是"类型ProjectName"。乔布斯不是一个集合。"

我开始使用Jobs类型,没有JsonArray属性和Jobs作为数组(Job[]),并得到此错误。

  public class Jobs { public Job[] JSON; }
    +       InnerException  {"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'ProjectName.Models.Jobs' because the type requires a JSON object (e.g. {'"name'":'"value'"}) to deserialize correctly.'r'n
    To fix this error either change the JSON to a JSON object (e.g. {'"name'":'"value'"}) or change the deserialized type to an array or a type that implements a collection interface
 (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.'r'n
Path '', line 1, position 1."}  System.Exception {Newtonsoft.Json.JsonSerializationException}

我将如何处理这个网站的JSON与。net 4.0任务模式?我希望在进入。net 4.5的await async模式之前让它工作。

回答更新:

下面是一个使用。net 4.5 async await模式和brumScouse的答案的例子。

 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);
 }

您需要引入System.Threading.Tasks命名空间。
注意:.Content上没有可用的.ReadAsString方法,这就是为什么我使用.ReadAsStringAsync方法。

使用.net 4.0任务模式,使用HTTPClient . readasasync将JSON反序列化为数组或列表

而不是手动启动你的模型尝试使用类似Json2csharp.com网站的东西。在示例JSON响应中,越完整越好,然后拉入生成的类。这样,至少去掉了一些移动的部分,将使您更容易地获得JSON的形状,从而使序列化器更轻松,并且您不应该添加属性。

只要让它工作,然后修改你的类名,以符合你的命名约定,并在以后添加属性。

编辑:好了,经过一番折腾,我已经成功地将结果反序列化为一个Job列表(我使用Json2csharp.com为我创建了这个类)

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();

这意味着你可以摆脱你的包含对象。值得注意的是,这不是一个与Task相关的问题,而是一个反序列化问题。

编辑2:

有一种方法可以在Visual Studio中获取JSON对象并生成类。只需复制选择的JSON,然后编辑>粘贴特殊>粘贴JSON为类。

http://blog.codeinside.eu/2014/09/08/visual工作室- 2013 -粘贴特殊json -和- xml/

var response = taskwithresponse.Result;
          var jsonString = response.ReadAsAsync<List<Job>>().Result;

返回类型取决于服务器,有时响应确实是一个JSON数组,但作为文本/明文发送

在请求中设置accept报头应该得到正确的类型:

client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

,然后可以序列化为JSON列表或数组。感谢@svick的评论,这让我很好奇它应该能工作。

我得到的异常没有配置接受头是System.Net.Http.UnsupportedMediaTypeException.

下面的代码更清晰,应该可以工作(未经测试,但在我的情况下可以工作):

    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>>();
相关文章: