JSON Literals for VB by ThinqLinq

JSON Literals for VB

One of the stand-out features of VB.Net since VB9 has been the inclusion of XML Literals. Followers of this blog should be well familiar with the concept because I first wrote about XML Literals way back in 2006. With them, we can imbed XML directly into our code as follows:

Dim value = <root>
                <child attrib="foo">bar</child>
            <root>

While XML Literals make the task of working with XML more of a joy than a necessary evil, they do add a certain level of complexity to the language. Any language feature then needs to be maintained moving forward. When I asked Anders about adding them to C#, he pointed to the ongoing maintenance issue along with the supposition that although XML was becoming a de-facto data persistence syntax, would adopting the literals into the language then set a precedence that they would need to support other persistence mechanisms when XML was replaced with some other syntax.

With the rise of REST and decline of SOAP, we have indeed seen the popularity of XML wane in favor of the more compact json syntax. The popularity is increased due to the fact that most JavaScript clients make parsing json into objects trivial. As a result, I have had conversations at conferences joking about the need for json literals in the language as well. At a recent conference an idea came to me which could actually make them (almost) a reality.

At its heart, json is simply a string representation of the JavaScript object structures. These object structures behave much like the .Net dynamic PropertyBag object. As a result, all we really need is a way to embed a long, multi-line string into our VB code and then parse it into a dynamic PropertyBag in order to consume it. Unfortunately, VB doesn’t support multi-line strings. However, it does support multi-line XML. All we need to do is wrap the multi line string inside of an XML element literal:

        Dim jsonLiteral = <js>[
            {author:'Jim Wooley', bookName:'LINQ in Action'},
            {author:'Frank Herbert', bookName:'Dune'},
            {author:'Joe Albahari', bookName:'LINQ Pocket Reference'},
            {author:'Joseph Rattz', bookName:'Pro LINQ'},
            {author:'Charlie Calvert', bookName:'Essential LINQ'}
        ]</js>

With that, we just need to decode the jsonLiteral.Value into a dynamic object. A quick search of Stack Overflow finds a number of handy options for this task. For the sake of this example, I’m just going to use the System.Web.Helpers.Json library that’s part of MVC. We’ll create an extension method to take an XElement and convert it into a dynamic object using the Json.Decode method:

<Extension>
Public Module JsonExtensions
    <Extension>
    Public Function JsonDecode(input As XElement) As Object
        Return Json.Decode(input.Value)
    End Function
End Module

With this in place, we can now operate on the literal just as if it was any other dynamic object type. Here’s the full code for this example.

Option Strict Off

Imports System.Runtime.CompilerServices
Imports System.Web.Helpers

Public Class Test1

    Public Sub TestJsonLiteral()
        Dim jsonLiteral = <js>[
            {author:'Jim Wooley', bookName:'LINQ in Action'},
            {author:'Frank Herbert', bookName:'Dune'},
            {author:'Joe Albahari', bookName:'LINQ Pocket Reference'},
            {author:'Joseph Rattz', bookName:'Pro LINQ'},
            {author:'Charlie Calvert', bookName:'Essential LINQ'}
        ]</js>

        For Each book In jsonLiteral.JsonDecode()
            Console.WriteLine(book.author)
        Next
    End Sub
End Class

<Extension>
Public Module JsonExtensions
    <Extension>
    Public Function JsonDecode(input As XElement) As Object
        Return Json.Decode(input.Value)
    End Function
End Module

I’m sure that there are features that this technique doesn’t cover (including LINQ because Object isn’t directly convertible to IEnumerable). I’m also not sure if this really has any practical benefit. It just is interesting to consider.

Posted on - Comment
Categories: VB) - VB Dev Center) - Linq to XML) -
comments powered by Disqus