Click here to Skip to main content
Click here to Skip to main content
Go to top

JavaScript Object Notation Support for .NET 2.0

, 24 Jan 2007
Rate this:
Please Sign up or sign in to vote.
A light weight alternative to XML

Introduction

JavaScript Object Notation, or JSON, is meant as a light weight alternative to XML when XML is just a bit heavy weight for what you are trying to achieve. Although JSON is not extensible, as it makes use of a fixed set of data types, it can be used to textually represent complex objects. JSON is a perfect data-interchange format when using technologies such as AJAX as your server side objects can be converted to JSON, sent to the client, evaluated in a client script and then manipulated to build dynamic adverts, menus etc.

Basic JSON Structure

JSON is comprised of two structures that all programmers are famaliar with, namely:

  • Objects - a collection of JSON types accessed by key. This can be thought of as IDictionary<string, JsonType>.
  • Arrays - a collection of JSON types accessed by index. This can be thought of as IList<JsonType>.

JSON also defines four primtive types:

  • String - a set of Unicode characters enclosed within double quotes. Basic control characers are supported as are four digit Unicode escapes.
  • Number - a number which can be negative, contain a fraction part and contain exponents.
  • Boolean - true or false.
  • null - a null value.

I don't want to bore you with the details, but links to the JSON specification can be found in the References section.

The code

All JSON types in the NetServ.Net.Json namespace implement the IJsonType interface. This interface allows the type to be identified by it's JsonTypeCode and also to have it write it's contents to a IJsonWriter. Implementations of the IJsonType interface are JsonString, JsonNumber, JsonBoolean, JsonArray, JsonObject and JsonNull. The interface is defined as follows:

using System;

namespace NetServ.Net.Json
{
    /// <summary>
    /// Defines a JavaScript Object Notation data type.
    /// </summary>
    public interface IJsonType
    {
        /// <summary>
        /// Writes the contents of the Json type using the specified
        /// <see cref="NetServ.Net.Json.IJsonWriter"/>.
        /// </summary>
        /// <param name="writer">The Json writer.</param>
        void Write(IJsonWriter writer);

        /// <summary>
        /// Gets the <see cref="NetServ.Net.Json.JsonTypeCode"/> of the type.
        /// </summary>
        JsonTypeCode JsonTypeCode {
            get;
        }
    }

    /// <summary>
    /// Defines the different types of Json structures and primitives.
    /// </summary>
    [Serializable()]
    public enum JsonTypeCode
    {
        /// <summary>
        /// A unicode encoded string.
        /// </summary>
        String,
        /// <summary>
        /// A number.
        /// </summary>
        Number,
        /// <summary>
        /// A boolean value represented by literal "true" and "false".
        /// </summary>
        Boolean,
        /// <summary>
        /// A null value.
        /// </summary>
        Null,
        /// <summary>
        /// A structured object containing zero or more name/value pairs, 
        /// delimited by curly brackets.
        /// </summary>
        Object,
        /// <summary>
        /// An unordered collection of values, delimted by square brackets.
        /// </summary>
        Array
    }
}

The IJsonWriter interface defines a JSON writer. It defines the basic methods needed to convert JSON types into text. An implementation of the interface is the JsonWriter class which writes the JSON text to an underlying TextWriter.

using System;

namespace NetServ.Net.Json
{
    /// <summary>
    /// Defines a JavaScript Object Notation writer.
    /// </summary>
    public interface IJsonWriter
    {
        /// <summary>
        /// Writes the start of an array to the underlying data stream.
        /// </summary>
        void WriteBeginArray();        

        /// <summary>
        /// Writes the end of an array to the underlying data stream.
        /// </summary>
        void WriteEndArray();

        /// <summary>
        /// Writes the start of an object to the underlying data stream.
        /// </summary>
        void WriteBeginObject();        

        /// <summary>
        /// Writes the end of an object to the underlying data stream.
        /// </summary>
        void WriteEndObject();

        /// <summary>
        /// Writes a object property name to the underlying data stream.
        /// </summary>
        /// <param name="value">The property name.</param>
        void WriteName(string value);

        /// <summary>
        /// Writes a raw string value to the underlying data stream.
        /// </summary>
        /// <param name="value">The string to write.</param>
        void WriteValue(string value);        
    }
}

Example of use within .NET

Here is a short example of how to construct a collection of JSON types and write the result to the console. Please note that a more complex example, including multiple nested objects and arrays, is included in the demo project download.

using System;
using NetServ.Net.Json;

namespace JsonTest
{
    [STAThread()]
    public class Program
    {
        public static void Main(string[] args) {

            JsonObject order = new JsonObject();
            JsonObject addr = new JsonObject();
            JsonArray items = new JsonArray();
            JsonObject item;     

            // Add some items into the array.

            item = new JsonObject();
            item.Add("ID", new JsonString("Chicken & Chips"));
            item.Add("Qty", new JsonNumber(2));
            item.Add("Price", new JsonNumber(1.50D));
            item.Add("Req", new JsonString("Plenty of salad."));
            items.Add(item);

            // The less verbose way.

            item = new JsonObject();
            item.Add("ID", "Pizza");
            item.Add("Qty", 1);
            item.Add("Price", 9.60D);
            item.Add("Size", "16\"");
            item.Add("Req", "");
            items.Add(item);

            // Add the address information.

            addr.Add("Street", "16 Bogus Street");
            addr.Add("City", "Bogustown");
            addr.Add("County", "Boguscounty");
            addr.Add("Postcode", "B0GU5");

            // Add the items and address into the order.

            order.Add("Items", items);
            order.Add("Address", addr);
            order.Add("Name", "Andrew Kernahan");
            order.Add("Tel.", "55378008");
            order.Add("Delivery", true);
            order.Add("Total", 12.60D);

            using(JsonWriter writer = new JsonWriter()) {

                // Get the container to write itself and all it's 
                // contained types to the writer.

                order.Write(writer);

                // Print the result.

                Console.WriteLine(writer.ToString());
            }
        }
    }
}

Using the JsonWriter will produce the most compact output. An alternative IJsonWriter is the IndentedJsonWriter which will produce indented output which can be easily read by humans should you need it to be. The above example will produce the following output when the IndentedJsonWriter is used.

{
    "Items":
    [
        {
            "ID": "Chicken & Chips",
            "Qty": 2,
            "Price": 1.5,
            "Req": "Plenty of salad."
        },
        {
            "ID": "Pizza",
            "Qty": 1,
            "Price": 9.6,
            "Size": "16\"",
            "Req": ""
        }
    ],
    "Address":
    {
        "Street": "16 Bogus Street",
        "City": "Bogustown",
        "County": "Boguscounty",
        "Postcode": "B0GU5"
    },
    "Name": "Andrew Kernahan",
    "Tel.": "55378008",
    "Delivery": true,
    "Total": 12.6
}

The JsonParser class is used to build JSON types read from a TextReader. Below is a simple example of how to parse and extract the JSON types. Please note that a more complex example can be found in the demo project download.

using System;
using System.IO;
using NetServ.Net.Json;

namespace JsonTest
{
    public class Program
    {
        [STAThread()]
        public static void Main(string[] args) {

            StringReader rdr = 
          new StringReader("{\"Name\":\"Andy\",\"Age\":23,\"Hungry?\":true}");

            // The parser takes any TextReader derived class as its source.

            JsonParser parser = new JsonParser(rdr, true);

            JsonObject obj = (JsonObject)parser.ParseObject();

            // Get the information from the object.

            JsonString name = (JsonString)obj["Name"];
            JsonNumber age = (JsonNumber)obj["Age"];
            JsonBoolean hungry = (JsonBoolean)obj["Hungry?"];

            // Print out the information.

            Console.WriteLine("Name:\t\t{0}", name.Value);
            Console.WriteLine("Age:\t\t{0}", age.Value.ToString());
            Console.WriteLine("Hungry?:\t{0}", hungry.Value.ToString());        
        }
    }
}

Example of use within JavaScript

If you are using JSON as an AJAX data-interchange format, using the JSON text within a client side script couldn't be easier as the example below shows.

function updateAdvertsCallback(result, context) {

    // result = [
    //  {"AdvertId":"left","InnerHTML":"Some text","ImageSrc":"animage""},
    //  {"AdvertId":"right","InnerHTML":"Some more text",
    //   "ImageSrc":"anotherimage""}
    // ]

    // Use the JavaScript compiler to parse the text and generate
    // the objects.

    var adverts = eval("(" + result + ")");

    // Then access the members as you would normally.

    for(var i = 0; i < adverts.length; ++i) {
        document.getElementById("advertHTML_" + 
              adverts[i].AdvertId).innerHTML = adverts[i].InnerHTML;
        document.getElementById("advertImg_" + 
              adverts[i].AdvertId).src = adverts[i].ImageSrc;
    }
}

You should be aware that JavaScript's eval function can be used to execute client side code when evaluated and should only be used when you trust the source of the JSON. The alternative is to use a parser which only recognises valid JSON input and ignores everything else. A good JavaScript JSON parser can be found here.

Points of Interest

Most of the JSON types in the NetServ.Net.Json namespace make use of C#'s cool ability to overload operators. This allows you to write really concise code which expresses exactly what you are trying to achieve.

// JsonBoolean jb = JsonBoolean.Get(true);
JsonBoolean jb = true;
// JsonNumber jn = new JsonNumber(42);
JsonNumber jn = 42;
// JsonString js = new JsonString("Hello World!");
JsonString js = "Hello World!";

Also the NetServ.Net.Json library is CLS compliant so it can be used in any .NET project developed in any CLS compliant language.

Unit Tests

Included in the download are the unit tests compiled for the library. The tests were written in conjunction with Marc Clifton's Advanced Unit Testing tool. An overview of the two hundred tests can be seen below.

UnitTest Overview

Conclusion

I admit that this is a bit of a light weight article (please go easy as its my first!), but hopefully you will appreciate how useful the JSON format is when XML is just too much for your needs.

References

Useful links

  • json.js - JavaScript JSON parser.
  • AJAX - CodeProject articles on AJAX.
  • AUT - Marc Clifton's Advanced Unit Testing tool.

History

  • 16 January 2007 - v1.1 initial public release.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

FACommenter
Software Developer
United Kingdom United Kingdom
No Biography provided

Comments and Discussions

 
GeneralVery effective and concise PinmemberHemant Ganpule18-Jun-13 3:12 
GeneralMy vote of 5 Pinmembermanoj kumar choubey18-Jul-12 20:47 
GeneralAbsolutely tremendous. Pinmembercolinhone20-Mar-12 2:47 
Generalneed help in creating json objects to dhtml Pinmemberchandru20117-Mar-11 17:35 
GeneralMy vote of 5 Pinmemberhaopang16-Nov-10 13:11 
GeneralMy vote of 5 PinmemberDan Tohatan21-Oct-10 6:32 
GeneralMy vote of 5 PinmemberGastonV22-Aug-10 20:43 
GeneralUnit tests in NUnit PinmemberMostafa Mahdieh8-May-10 13:06 
GeneralThe best! Pinmemberujeenboy2-Mar-09 2:44 
QuestionAbout licensing PinmemberAnash P Oommen21-Nov-08 18:09 
AnswerRe: About licensing PinmemberAndyKernahan21-Nov-08 22:42 
QuestionCan it Support by .net 1.1? PinmemberWaitd8-Sep-08 7:27 
GeneralNow Superseded in .NET 3.5 PinmemberGavin Harriss26-Jun-08 14:41 
GeneralCongratulations !! Pinmemberalitokmen19-May-08 10:45 
GeneralAt last PinmemberTim Schwallie29-Jan-07 17:58 
GeneralRe: At last Pinmemberdave.dolan2-Feb-07 9:39 
GeneralRe: At last PinmemberTim Schwallie8-Feb-07 17:14 
GeneralRe: At last Pinmemberdave.dolan8-Feb-07 17:19 
GeneralRe: At last PinmemberTim Schwallie11-Feb-07 16:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 24 Jan 2007
Article Copyright 2007 by FACommenter
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid