Parsing List of JSON Elements as List With JSON.Net

I've been a big fan of JSON.Net for the past few years. Always helping me with less code and high-performance conversion of JSON to C# objects. Thanks to James who made it possible as the fastest framework for manipulating JSON with great documentation. This article describes a JSON format where a list of JSON objects is present with no root elements. This would be easy if you have a root element; you could then use the JObject of json.net. But in case you don't then this would throw an exception.

Let us say we have a list of elements in the JSON data:
  1. [  
  2.         {  
  3.             "major": 4,  
  4.             "minor": 0,  
  5.             "profile": "client",  
  6.             "servicePack": null,  
  7.             "url": "http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=5765d7a8-7722-4888-a970-ac39b33fd8ab"  
  8.         },  
  9.         {  
  10.             "major": 4,  
  11.             "minor": 0,  
  12.             "profile": "full",  
  13.             "servicePack": null,  
  14.             "url": "http://www.microsoft.com/downloads/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992&displaylang=en"  
  15.         },  
  16.         {  
  17.             "major": 3,  
  18.             "minor": 5,  
  19.             "profile": "client",  
  20.             "servicePack": 1,  
  21.             "url": "http://www.microsoft.com/downloads/details.aspx?FamilyId=8CEA6CD1-15BC-4664-B27D-8CEBA808B28B&displaylang=en"  
  22.         },  
  23.         {  
  24.             "major": 3,  
  25.             "minor": 5,  
  26.             "profile": "full",  
  27.             "servicePack": 1,  
  28.             "url": "http://go.microsoft.com/fwlink/?LinkId=124150"  
  29.         },  
  30.         {  
  31.             "major": 3,  
  32.             "minor": 0,  
  33.             "profile": "full",  
  34.             "servicePack": 1,  
  35.             "url": "http://www.microsoft.com/downloads/details.aspx?FamilyId=10CC340B-F857-4A14-83F5-25634C3BF043&displaylang=en"  
  36.         },  
  37.         {  
  38.             "major": 2,  
  39.             "minor": 0,  
  40.             "profile": "full",  
  41.             "servicePack": 2,  
  42.             "url": "http://www.microsoft.com/downloads/details.aspx?familyid=5B2C0358-915B-4EB5-9B1D-10E506DA9D0F&displaylang=en"  
  43.         },  
  44.         {  
  45.             "major": 1AAA,  
  46.             "minor": 1,  
  47.             "profile": "full",  
  48.             "servicePack": 1,  
  49.             "url": "http://www.microsoft.com/downloads/details.aspx?FamilyID=a8f5654f-088e-40b2-bbdb-a83353618b38&DisplayLang=en"  
  50.         }  
  51.     ]   
  52.   
  53. // Sample taken from http://www.hanselman.com/blog/NuGetPackageOfTheWeek4DeserializingJSONWithJsonNET.aspx 
You can use simple Jsonconvert.Deserialize<yourType>(jsonString) to get the typed object from the JSON. But this can throw an error if the items in JSON have a field with an incorrect value. Let's an int field have some alphabetic character. The exception will be thrown for parsing and you'll have very little details on the error.
 
Now if you need to parse it as a list and let's say you want to find elements with fields that are not of the correct type as it should be then we can filter them out and log them somewhere. And so you will get a complete list of correct items and corrupted data.
 
We'll use a JArray class from the namespace Newtonsoft.Json.Linq to parse the data as a list of arrays of objects and then we'll convert one by one each item to a typed object and add it to the list. Here's the sample generic deserializer that can parse JSON and get the valid and invalid elements.
 
Converter/Deserializer
  1. public static List<string> InvalidJsonElements;  
  2. public static IList<T> DeserializeToList<T>(string jsonString)  
  3. {  
  4.     InvalidJsonElements = null;  
  5.     var array = JArray.Parse(jsonString);  
  6.     IList<T> objectsList = new List<T>();  
  7.    
  8.     foreach (var item in array)  
  9.     {  
  10.         try  
  11.         {  
  12.             // CorrectElements  
  13.             objectsList.Add(item.ToObject<T>());  
  14.         }  
  15.         catch (Exception ex)  
  16.         {  
  17.             InvalidJsonElements = InvalidJsonElements ?? new List<string>();  
  18.             InvalidJsonElements.Add(item.ToString());  
  19.         }  
  20.     }  
  21.    
  22.     return objectsList;  

Usage
  1. Product productObj = new Product();  
  2. IList<Product> validProdcuts;  
  3. IList<string> invalidProductItemInJson;  
  4. string jsonString = "[{json specified above}]";  
  5.    
  6. // Call the deserializer  
  7. validProdcuts = JsonHelper.DeserializeToList<Product>(jsonString);  
  8.    
  9. // Check for errors  
  10. if (JsonHelper.InvalidJsonElements.Count != 0)  
  11. {  
  12.     invalidProductItemInJson = InvalidJsonElements;  
  13.      
  14.     // Here we have invalid items of json now we are rectified with  
  15.     // the problematic data from json  

So here you can see that you'll have valid items in the list and invalid errors. For an example of the preceding JSON data, the last element has an invalid value to an int field major as '1AAA'.