Tip/Trick: Building a ToJSON() Extension Method using .NET 3.5
Earlier this year I blogged about a new language extensibility feature of C# and VB called "Extension Methods".
Extension methods allow developers to add new methods to the public contract of an existing CLR type, without having to sub-class it or recompile the original type. In doing so they enable a variety of useful scenarios (including LINQ). They also provide a really convenient way to add a dash of "syntactic sugar" into your code.
Over the last few months I've been making a list of cool extension methods that I plan to sit down and implement when I get some free time (not sure when that is... but at least I can still have fun coming up with the ideas!) Two of the scenarios I added to my extension method list were easy methods to automate generating JSON (JavaScript Object Notation) or XML serialization strings for any .NET object.
Simple Scenario: The ToJSON() extension method
Assume I had a Person object defined like below (note: I'm using the new automatic properties feature to implement it):
I'd like to then be able to initialize a collection of Person objects and programmatically retrieve a JSON string representation of them by just calling a ToJSON() extension method on it like below:
This would work just like the built-in ToString() method on the Object class in .NET today - except that it would generate a JSON-format representation of the collection that I could use for AJAX scenarios on the client:
Note: Clicking on the hour-glass in the debugger above allows us to bring up the Text Visualizer in VS to see a clean version of the JSON serialization:
This string format could then be used within JavaScript on the client to instantiate an appropriate JavaScript object that represents my collection (note: ASP.NET AJAX has a built-in JavaScript library to support this).
Implementing the ToJSON Extension Method
Implementing a basic ToJSON() extension method is pretty simple. All I needed to-do was use the JavaScriptSerializer class in the System.Web.Script.Serialization namespace, and define two extension methods like below. One of the methods serializes an object graph any levels deep, the other is an overloaded version that allows you to optionally constrain how deep it recurses (for example: ToJSON(2) would serialize only 2 levels deep in the object graph).
Note that the ToJSON() extension methods above are defined for type "Object" - which means they can be used with all objects in .NET (not just collections). This means that in addition to calling .ToJSON() on collections like I did above, I could also have called ToJSON() on individual Person objects, as well as any other .NET datatype.
To use the extension method, all I need to-do is add a using statement at the top of my program that references the namespace it was defined within:
VS 2008 then takes care of providing intellisense and compile time support for it to all objects:
Note: In addition to the JavaScriptSerializer class, .NET 3.5 also now includes a new System.Runtime.Serialization.DataContractJsonSerializer class that you can use for JSON serialization/deserialization.
Summary
Hopefully the above sample provides a simple example of how you can easily encapsulate useful functionality into extension methods. Overtime I expect that we'll start to see some nice utility libraries come out that provide helpful extension methods like above.
I'd be curious to see suggestions for other common scenarios you think should be packaged up into re-usable extension methods (feel free to use the comments of this post to suggest them). We can then figure out how to get a good CodePlex project created that bundles up some of them together into one library to easily use.
Hope this helps,
Scott
P.S. Please check out my Tips/Tricks and Tutorials page to find other useful ASP.NET and .NET posts I've done.