Search code examples
c#.netjsonasp.net-web-api

How to parse this 3rd party JSON service using .NET?


I am trying to read a web service api via my .NET desktop application. I have tried the following, but nothing is being populated. Via Fiddler, if I click on the [Raw] tab, the response looks like:

HTTP/1.1 200 OK 
Date: Fri, 01 Aug 2014 21:49:48 GMT 
Server: Apache
X-Powered-By: PHP/5.3.3 
Connection: close 
Content-Length: 125478
Access-Control-Allow-Origin: * 
Content-Type: application/json
Content-Language: en

{"request":{"command":"project","project_id":"XYZ123"},"project":[{"project_id":"XYZ123","name":"Project Financials","description":"Sales","state":"CA","dept":"Finance","modified":"2014-08-01","data":[["20140801", 112423],["20140731", 689944],["20140730", 9855], ["20140729", 13118], ["20140728", 9448],
... more data ...
["20140318", 1546], ["20140317", 5467], ["20140316", 19578], ["20140315", 90158]]}]}

I would like to capture the data points, i.e. the "data" from the above JSON segment. For this I have a simple class as follows:

public class DailySales
{
    public datetime Date { get; set; }
    public int UnitsSold { get; set; }
}

And here is my web service code:

private void GetSales()
{
      var webClient = new WebClient();
      webClient.OpenReadCompleted += webClient_OpenReadCompleted;
      webClient.OpenReadAsync(new Uri("http://3rdPartySite.com"));
}

void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
      var json = new DataContractJsonSerializer(typeof(List<DailySales>));
      var data = (List<DailySales>)json.ReadObject(e.Result); // returns null  
}

Any tips on what I am missing would be appreciated.


Solution

  • Well, your json isn't deserializing because your class model doesn't match it at all.

    First, create a proper model (this was generated using json2csharp):

    public class Request
    {
        public string command { get; set; }
        public string project_id { get; set; }
    }
    
    public class Project
    {
        public string project_id { get; set; }
        public string name { get; set; }
        public string description { get; set; }
        public string state { get; set; }
        public string dept { get; set; }
        public string modified { get; set; }
        public List<List<object>> data { get; set; }
    }
    
    public class RootObject
    {
        public Request request { get; set; }
        public List<Project> project { get; set; }
    }
    

    Note data is generated as a List<List<object>> as it doesn't recognize a common pattern. You can change that to a class containing an int and a DateTime object, but you'll have to convert that int in your JSON to a DateTime object manually.

    On the webrequest side, you can use HttpClient along with the new async-await feature in .NET 4.5, along with Json.NET:

    public async Task RequestAndDeserializeJson()
    {
        var httpClient = new HttpClient();
        var json = await httpClient.GetAsStringAsync("http://3rdPartySite.com");
        RootObject obj = JsonConvert.Deserialize<RootObject>(json);
    }
    

    If you only want to extract the data points, you can use JObject.Parse in the Json.NET api:

    var jobject = JObject.Parse(json);
    
    // Extract data points only
    var dataPoints = jobject["project"]["data"];