Parsing a complex JSON result with C#
Use the below classes for de-serializing using JSON.Net
public class ResponseActual
{
[JsonProperty("response")]
public Response2 Response { get; set; }
}
public class Response2
{
[JsonProperty("result")]
public Result Result { get; set; }
[JsonProperty("uri")]
public string Uri { get; set; }
}
public class Result
{
[JsonProperty("Contacts")]
public Contacts Contacts { get; set; }
}
public class Contacts
{
[JsonProperty("row")]
public IList<Row> Row { get; set; }
}
public class Row
{
[JsonProperty("no")]
public string No { get; set; }
[JsonProperty("FL")]
public IList<FL> FL { get; set; }
}
public class FL
{
[JsonProperty("content")]
public string Content { get; set; }
[JsonProperty("val")]
public string Val { get; set; }
}
//To De-serialize
ResponseActual respone = JsonConvert.DeserializeObject<ResponseActual>(jSON_sTRING)
//Get the contacts list
List<FL> contacts = respone.Response.Result.Contacts.Row[0].FL.ToList();
//Now Get the required value using LINQ
var value = contacts.Where<FL>((s, e) => s.Val =="Email").Select(x=>x.Content).Single();
You may also checkout this - Deserializing JSON to .NET object using Newtonsoft (or LINQ to JSON maybe?)
DigiOz Multimedia
Pete Soheil is the Creator and Owner of DigiOz Multimedia Inc., a Chicago-IL based company that specializes in the creation of Windows, Web and Mobile Application Development in a variety of Programming Languages, including C#, VB.NET, ASP.NET, ASP, VC++, GCC, PHP and Perl as well as Cloud based Platforms.
Updated on July 09, 2022Comments
-
DigiOz Multimedia almost 2 years
I am trying to parse the following complex JSON result, which is returned from the Zoho Crm API:
{ "response": { "result": { "Contacts": { "row": [ { "no":"1", "FL": [ { "content":"555555000000123456", "val":"CONTACTID" }, { "content":"555555000000012345", "val":"SMOWNERID" }, { "content":"John Doe", "val":"Contact Owner" }, { "content":"Pete", "val":"First Name" }, { "content":"Smith", "val":"Last Name" }, { "content":"[email protected]", "val":"Email" }, { "content":"5555551000000012346", "val":"SMCREATORID" }, { "content":"Jane Doe", "val":"Created By" }, { "content":"555555000000012347", "val":"MODIFIEDBY" }, { "content":"Doris Doe", "val":"Modified By" }, { "content":"2013-06-14 17:24:10", "val":"Created Time" }, { "content":"2013-06-14 17:24:10", "val":"Modified Time" }, { "content":"2013-06-14 17:28:05", "val":"Last Activity Time" } ] }, { ... } ] } }, "uri":"/crm/private/json/Contacts/getRecords" }
}
Here is how my Object looks:
public class Contact { [JsonProperty(PropertyName = "CONTACTID")] public string ContactID { get; set; } [JsonProperty(PropertyName = "SMOWNERID")] public string OwnerID { get; set; } [JsonProperty(PropertyName = "Contact Owner")] public string ContactOwner { get; set; } [JsonProperty(PropertyName = "First Name")] public string FirstName { get; set; } [JsonProperty(PropertyName = "Last Name")] public string LasName { get; set; } [JsonProperty(PropertyName = "Email")] public string Email { get; set; } [JsonProperty(PropertyName = "SMCREATORID")] public string CreatorID { get; set; } [JsonProperty(PropertyName = "Created By")] public string CreatedBy { get; set; } [JsonProperty(PropertyName = "MODIFIEDBY")] public string ModifiedByID { get; set; } [JsonProperty(PropertyName = "Modified By")] public string ModifiedBy { get; set; } [JsonProperty(PropertyName = "Created Time")] public DateTime CreatedTime { get; set; } [JsonProperty(PropertyName = "Modified Time")] public DateTime ModifiedTime { get; set; } [JsonProperty(PropertyName = "Last Activity Time")] public DateTime LastActivityTime { get; set; } }
The "row" pattern repeats (no 1, 2, 3 ...) so what I am basically trying to get is a Generic List of Objects of this type. I am trying to using JSON.NET, but I am open to other suggestions if it makes this any easier.
This doesn't work in this case obviously:
var response = JsonConvert.DeserializeObject<Contact>(jsonString);
And neither does this:
var deserializedObjects = JsonConvert.DeserializeObject<List<Contact>>(jsonString);
Here is a workaround I have put together to parse this using JavaScriptSerializer, but it is by far one of my worst code blocks ever!
List<Contact> loContactList = new List<Contact>(); Contact loContact = null; Dictionary<string, object> dictionary = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(jsonString); var response = (Dictionary<string, object>)dictionary["response"]; var result = (Dictionary<string, object>)response["result"]; var contacts = (Dictionary<string, object>)result["Contacts"]; var row = (ArrayList)contacts["row"]; foreach (var item in row) { var loArrayItem = (Dictionary<string, object>)item; var fl = (ArrayList)loArrayItem["FL"]; loContact = new Contact(); foreach (var contactitem in fl) { var contactdict = (Dictionary<string, object>)contactitem; string val = (string)contactdict["val"]; string content = (string)contactdict["content"]; if (val == "CONTACTID") { loContact.ContactID = content; } else if (val == "SMOWNERID") { loContact.OwnerID = content; } else if (val == "Contact Owner") { loContact.ContactOwner = content; } else if (val == "First Name") { loContact.FirstName = content; } else if (val == "Last Name") { loContact.LastName = content; } else if (val == "Email") { loContact.Email = content; } else if (val == "SMCREATORID") { loContact.CreatorID = content; } else if (val == "Created By") { loContact.CreatedBy = content; } else if (val == "MODIFIEDBY") { loContact.ModifiedByID = content; } else if (val == "Modified By") { loContact.ModifiedBy = content; } else if (val == "Created Time") { loContact.CreatedTime = Convert.ToDateTime(content); } else if (val == "Modified Time") { loContact.ModifiedTime = Convert.ToDateTime(content); } else if (val == "Last Activity Time") { loContact.LastActivityTime = Convert.ToDateTime(content); } } loContactList.Add(loContact); }
I have gone through other similar posts on StackOverflow and none of them seem to provide a solution for this problem. Does anyone have a solution for this? My goal is to parse this JSON response in a more elegant way, which doesn't involve a million dictionary objects and ArrayList! Any help would be appreciated.
Thanks, Pete
Update 7/2/13:
Based on Manvik's suggestion, I put together the following additional solution:
public class ResponseActual { [JsonProperty("response")] public Response2 Response { get; set; } } public class Response2 { [JsonProperty("result")] public Result Result { get; set; } [JsonProperty("uri")] public string Uri { get; set; } } public class Result { [JsonProperty("Contacts")] public Contacts Contacts { get; set; } } public class Contacts { [JsonProperty("row")] public IList<Row> Row { get; set; } } public class Row { [JsonProperty("no")] public string No { get; set; } [JsonProperty("FL")] public IList<FL> FL { get; set; } } public class FL { [JsonProperty("content")] public string Content { get; set; } [JsonProperty("val")] public string Val { get; set; } } List<Contact> loContactList = new List<Contact>(); Contact loContact = null; ResponseActual respone = JsonConvert.DeserializeObject<ResponseActual>(jsonString); foreach (var row in respone.Response.Result.Contacts.Row) { loContact = new Contact(); var rowItem = row.FL.ToList(); try { loContact.ContactID = rowItem.Where<FL>((s, t) => s.Val == "CONTACTID").Select(x => x.Content).Single(); } catch { } try { loContact.OwnerID = rowItem.Where<FL>((s, t) => s.Val == "SMOWNERID").Select(x => x.Content).Single(); } catch { } try { loContact.ContactOwner = rowItem.Where<FL>((s, t) => s.Val == "Contact Owner").Select(x => x.Content).Single(); } catch { } try { loContact.FirstName = rowItem.Where<FL>((s, t) => s.Val == "First Name").Select(x => x.Content).Single(); } catch { } try { loContact.LastName = rowItem.Where<FL>((s, t) => s.Val == "Last Name").Select(x => x.Content).Single(); } catch { } try { loContact.Email = rowItem.Where<FL>((s, t) => s.Val == "Email").Select(x => x.Content).Single(); } catch { } try { loContact.CreatorID = rowItem.Where<FL>((s, t) => s.Val == "SMCREATORID").Select(x => x.Content).Single(); } catch { } try { loContact.CreatedBy = rowItem.Where<FL>((s, t) => s.Val == "Created By").Select(x => x.Content).Single(); } catch { } try { loContact.ModifiedByID = rowItem.Where<FL>((s, t) => s.Val == "MODIFIEDBY").Select(x => x.Content).Single(); } catch { } try { loContact.ModifiedBy = rowItem.Where<FL>((s, t) => s.Val == "Modified By").Select(x => x.Content).Single(); } catch { } try { loContact.CreatedTime = Convert.ToDateTime(rowItem.Where<FL>((s, t) => s.Val == "Created Time").Select(x => x.Content).Single()); } catch { } try { loContact.ModifiedTime = Convert.ToDateTime(rowItem.Where<FL>((s, t) => s.Val == "Modified Time").Select(x => x.Content).Single()); } catch { } try { loContact.LastActivityTime = Convert.ToDateTime(rowItem.Where<FL>((s, t) => s.Val == "Last Activity Time").Select(x => x.Content).Single()); } catch { } loContactList.Add(loContact); }
-
DigiOz Multimedia almost 11 yearsThank you for your hint. My question is how would I go about doing that?
-
DigiOz Multimedia almost 11 yearsThank you Manvik! Admittedly, I was looking for something a bit more automated, but this solution is certainly better then having all those nested Dictionaries.
-
DigiOz Multimedia over 10 yearsNo! You wouldn't catch me dead exporting JSON like this! The credit entirely goes to the geniuses at zoho.com.