JSON Serializers In .NET

I was introduced to the various serialization options in .NET while trying to build the JSON and XML filter for ASP.NET MVC. In this post I’ll take a look at the different JSON serializers in .NET and the reasons to pick one over the other.

JavaScriptSerializer

The JavaScriptSerializer lives in the System.Web.Script.Serialization namespace and the usage is fairly straight forward for serialization:

JavaScriptSerializer serializer = new JavaScriptSerializer();
String json = serializer.Serialize(data);

For deserialization however, there is a minor annoyance in that the deserializer accepts a generic type along with the content:

serializer.Deserialize<T>(String s)

which can be a problem if the type T is not known at compile time and needs to be dynamic. The work around is a bit ugly as I learnt because it uses reflection to create a generic method but it works:

var result = typeof(JavaScriptSerializer).GetMethod("Deserialize")
             .MakeGenericMethod(JsonDataType)
             .Invoke(serializer, new object[] { inputContent });

The JavaScriptSerializer is excellent for general purpose serialization and deserialization, however, one downside is that it cannot handle circular references.

A useful feature of the JavaScriptSerializer is that you can also implement a custom JavaScriptConverter and pass that in to JavaScriptSerializer for fine-grained control over the serialization/deserialization. However, for it to be really useful you need to know the types at compile time and have references to those types. This really limits the usefulness of this feature because by referencing those classes your code becomes tightly coupled so you cannot easily use it in something like an MVC filter.

The JavaScriptSerializer includes all public fields and properties for serialization by default which makes it useful when working with auto-generated classes or if you don’t have access to the source. This is different from how DataContractJsonSerializer works.

DataContractJsonSerializer

The DataContractJsonSerializer lives in the System.Runtime.Serialization.Json namespace. Unlike the JavaScriptSerializer, the DataContractJsonSerializer is a contract-based serializer so classes or members need to have the [DataContract], [DataMember] or the [Serializable] attribute.

[Serializable]
class Person {
    public String Name;
    public Int32 Age;
}

...

String json;
using (var stream = new MemoryStream()) {
    DataContractJsonSerializer serializer =
       new DataContractJsonSerializer(data.GetType());
    serializer.WriteObject(stream, data);
    json = Encoding.UTF8.GetString(stream.ToArray());
}

And for deserialization:

using(var stream = new MemoryStream(Encoding.Unicode.GetBytes(json)) {
    Object data = serializer.ReadObject(stream);
}

Since DataContractJsonSerializer is contract based and relies on attributes, it is not particularly suitable for auto-generated classes (unless they have these attributes) or when source is not accessible because the relevant attributes cannot be added at runtime as far as I know. However, for other situations attributes are an easy way to control the serialization aspects.

The most compelling feature of the DataContractJsonSerializer is that it can handle complex object graphs with circular references. This makes it particularly useful with the Entity Framework 4.0 which now support T4 templates allowing required [Serializable] or [DataMember] attributes to be added to auto-generated classes.

Update: In .NET 3.5 SP1, DataContractSerializer added support for classes without attributes (or POCO objects).

Json in MVC

The System.Web.Mvc namespace contains the Json function intended for use within ASP.NET MVC. There is no real reason to use it outside of ASP.NET MVC when JavaScriptSerializer and DataContractJsonSerializer are available. This function makes it extremely easy to serialize objects to a JSON string. It is not intended for deserialization, however, serialization is just one call:

String content = Json(data);

3 Responses



This article is no longer open for comments