Deserialize JSON to Array or List with HTTPClient .ReadAsAsync using .NET 4.0 Task pattern

Instead of handcranking your models try using something like the Json2csharp.com website. Paste In an example JSON response, the fuller the better and then pull in the resultant generated classes. This, at least, takes away some moving parts, will get you the shape of the JSON in csharp giving the serialiser an easier time and you shouldnt have to add attributes.

Just get it working and then make amendments to your class names, to conform to your naming conventions, and add in attributes later.

EDIT: Ok after a little messing around I have successfully deserialised the result into a List of Job (I used Json2csharp.com to create the class for me)

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

And an edit to your code:

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

This means you can get rid of your containing object. Its worth noting that this isn't a Task related issue but rather a deserialisation issue.

EDIT 2:

There is a way to take a JSON object and generate classes in Visual Studio. Simply copy the JSON of choice and then Edit> Paste Special > Paste JSON as Classes. A whole page is devoted to this here:

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


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

The return type depends on the server, sometimes the response is indeed a JSON array but sent as text/plain

Setting the accept headers in the request should get the correct type:

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

which can then be serialized to a JSON list or array. Thanks for the comment from @svick which made me curious that it should work.

The Exception I got without configuring the accept headers was System.Net.Http.UnsupportedMediaTypeException.

Following code is cleaner and should work (untested, but works in my case):

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