Уничтожить JSON в массив или список с помощью HTTPClient.ReadAsAsync с использованием .NET 4.0 Шаблон задачи

290
32

Я пытаюсь десериализовать JSON, возвращенный с http://api.usa.gov/jobs/search.json?query=nursing+jobs, используя шаблон задачи .NET 4.0. Он возвращает этот JSON ( "Загрузить данные JSON" @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();
...
}

Работа и класс работы:


  [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, статус
Faulted. InnerException - "Тип ProjectName.Jobs - это не коллекция".


Я начал с типа 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? Я хотел бы получить эту работу, прежде чем перейти к шаблону await async в .NET 4.5.


ANSWER UPDATE:


Вот пример использования асинхронного ожидания .NET 4.5 с ответом на 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.

спросил(а) 2021-01-14T02:12:36+03:00 1 неделя назад
1
Решение
326

Вместо ручного управления ваши модели попробуйте использовать что-то вроде веб-сайта Json2csharp.com. Вставить. В примере ответа JSON, чем полнее, тем лучше, а затем вытащите результирующие сгенерированные классы. Это, по крайней мере, забирает некоторые движущиеся части, даст вам форму JSON в csharp, давая сериализатору более легкое время, и вам не нужно добавлять атрибуты.


Просто заработайте, а затем внесите изменения в имена классов, чтобы соответствовать вашим соглашениям об именах и позже добавлять атрибуты.


EDIT:
Хорошо после небольшого беспорядка. Я успешно отменил результат в списке заданий (я использовал 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();


Это означает, что вы можете избавиться от своего объекта. Стоит отметить, что это не проблема, связанная с задачей, а скорее проблема десериализации.


ИЗМЕНИТЬ 2:


Существует способ взять объект JSON и сгенерировать классы в Visual Studio. Просто скопируйте JSON по выбору, а затем Edit > Paste Special > Paste JSON в качестве классов. Целая страница посвящена этому:


http://blog.codeinside.eu/2014/09/08/Visual-Studio-2013-Paste-Special-JSON-And-Xml/

ответил(а) 2021-01-14T02:12:36+03:00 1 неделя назад
144

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

ответил(а) 2021-01-14T02:12:36+03:00 1 неделя назад
60

Тип возврата зависит от сервера, иногда ответ действительно является массивом JSON, но отправляется как text/plain


Настройка заголовков accept в запросе должна быть верна:


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

который затем может быть сериализован в список или массив JSON.
Спасибо за комментарий от @svick, из-за которого мне было любопытно, что он должен работать.


Исключение, которое я получил без настройки заголовков accept, было 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 = response.Content.ReadAsAsync<List<Job>>();

ответил(а) 2021-01-14T02:12:36+03:00 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема