LINQ to JSON – Checking for an Object or Array

 

I was writing an event handler for my book that consumes a stream of JSON from a RESTful service. The handler is called when one of several asynchronous events is invoked. All of these events request a steam of either 1 or more products to be returned as JSON. So I wanted this handler to be able to consume the JSON whether it was a single product or an array of products.

The JSON is not wrapped, so a single object will not convert to a JsonArray. What I really wanted was to avoid writing the same LINQ to JSON query just to change out if it was looking for an object or an array. The way I handled this is to parse the raw JSON (a string variable) into a JsonArray object. If the JSON is a single object then when it is cast to a JsonArray it will be null. So at that point I know if it is an array of products or a single product.

Then, in the IF statement if it is a single object I parse the JSON into a JsonObject, create an instance of a JsonArray and add the JsonObject to the JsonArray. If the JSON data can be parsed into a JsonArray, the ELSE section parses it into a JsonArray. So in the end I have a JsonArray of either 1 or more objects. Why is this important? Because the query can now be written to find a list of products without having to handle wether it comes form a JsonObject or against a JsonArray.

C#

private void ParseProducts_AsJson(object sender, DownloadStringCompletedEventArgs e)
  
{
  
string raw = e.Result;
  
 
  
JsonArray json;
  
if (JsonArray.Parse(raw) as JsonArray == null)
  
json = new JsonArray {JsonObject.Parse(raw) as JsonObject};
  
else
  
json = JsonArray.Parse(raw) as JsonArray;
  
 
  
var query = from product in json
  
select new Product
  
{
  
ProductId = (int)product["ProductId"],
  
ProductName = (string)product["ProductName"],
  
UnitPrice = (decimal)product["UnitPrice"]
  
};
  
List<Product> products = query.ToList() as List<Product>;
  
lstProducts.DataContext = products;
  
}

VB

Private Sub ParseProducts_AsJson(ByVal sender As Object, _
  
ByVal e As DownloadStringCompletedEventArgs)
  
Dim raw As String = e.Result
  
 
  
Dim json As JsonArray
  
If TryCast(JsonArray.Parse(raw), JsonArray) Is Nothing Then
  
json = New JsonArray With _
  
{TryCast(JsonObject.Parse(raw), JsonObject)}
  
Else
  
json = TryCast(JsonArray.Parse(raw), JsonArray)
  
End If
  
 
  
Dim query = _
  
From product In json _
  
Select New Product With 
  
{.ProductId = CInt(Fix(product("ProductId"))), _
  
.ProductName = CStr(product("ProductName")), _
  
.UnitPrice = CDec(product("UnitPrice"))}
  
Dim products As List(Of Product) = _
  
TryCast(query.ToList(), List(Of Product))
  
lstProducts.DataContext = products
End Sub

If there is a better way, I am certainly open to it. I’d love to see some additional methods on these objects to allow a little more variation. But overall I am thrilled to see LINQ to JSON! Now, too bad I can’t create an anonymous type from this LINQ query and bind it to the XAML. Wishes and dream for the next version :)

DotNetKicks Image
Tweet Post Share Update RSS

Hi, I'm John Papa. I author this blog, create courses for Pluralsight and am a Google Developer Expert and Microsoft Regional Director. I travel speaking at events and train technology thought leaders

Tags:
Silverlight