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
    #1 Dew Drop - September 15, 2008 | Alvin Ashcraft's Morning Dew on 9.15.2008 at 8:17 AM

    Pingback from Dew Drop - September 15, 2008 | Alvin Ashcraft's Morning Dew



    Leave a Comment