user118190
user118190

Reputation: 2179

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.

Upvotes: 1

Views: 341

Answers (2)

Amit
Amit

Reputation: 669

You are trying to deserialize the response into a class model that doesn't match the JSON. For starters your root model class has to be defined which would have the members request of type Request and project of type List<Project>.

Subsequently the data field should be a member of Project model with type List<List<DailySales>>.

The class models would look like the following:

public class JsonRoot
{
    public Request request { get; set; }
    public List<Project> project { get; set; }
}

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; }
    // Other Fields
    public List<List<DailySales>> data { get; set; }
}

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

Upvotes: 1

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149538

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"];

Upvotes: 3

Related Questions