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
{
public interface IJsonType
{
void Write(IJsonWriter writer);
JsonTypeCode JsonTypeCode {
get;
}
}
[Serializable()]
public enum JsonTypeCode
{
String,
Number,
Boolean,
Null,
Object,
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
{
public interface IJsonWriter
{
void WriteBeginArray();
void WriteEndArray();
void WriteBeginObject();
void WriteEndObject();
void WriteName(string value);
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;
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);
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);
addr.Add("Street", "16 Bogus Street");
addr.Add("City", "Bogustown");
addr.Add("County", "Boguscounty");
addr.Add("Postcode", "B0GU5");
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()) {
order.Write(writer);
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}");
JsonParser parser = new JsonParser(rdr, true);
JsonObject obj = (JsonObject)parser.ParseObject();
JsonString name = (JsonString)obj["Name"];
JsonNumber age = (JsonNumber)obj["Age"];
JsonBoolean hungry = (JsonBoolean)obj["Hungry?"];
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) {
var adverts = eval("(" + result + ")");
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 = true;
JsonNumber jn = 42;
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.
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.