DataContractJsonSerializer Versus JavaScriptSerializer : Changing Field Names

Oh my, where do I start, simplicity or contract inclusivity.  I generally like simplicity which leans me towards using the JavaScriptSerializer, but I had some doubts when I kept reading that it was deprecated.  I finally came across a Scott Gu’s response in this post by Aaron Lerch, that indicates the JavaScriptSerializer is un-deprecated.  So which to use?  Here are some of the pros and cons:

DataContractJsonSerializer

Pros:

  • You can control the property names when serializing.  This can be nice if you have JSON coming in from a third party and the fields are like “a” or “exp”.
  • WCF uses this for serialization/deserialization

Cons:

  • Does not map enumerations.  You get an exception when trying to deserialize into a enum.
  • From what I’ve seen it’s slower than the JavaScriptSerializer.
  • You have to write more code to do a simple serialization.

JavaScriptSerializer

Pros:

  • Much easier to deal with.
  • Handles enumerations.

Cons:

  • Cannot control property names when serializing.

Looking at the cons for DataContractJsonSerializer, it would seem like you wouldn’t want to use it unless you were doing some WCF work.  It just happened the other day that I was working on a couple of projects where I decided to use one serializer in one project and the other in the other project.  My thinking was that if you’re working with JSON, and the class at hand in somewhat internal and isolated to some component, use the simple JavaScriptSerializer.  You loose property name management, but so what, keep it simple.  On the other hand, this other project I was working on I thought I might expose it publically for other people to use.  In this case I wouldn’t want property names like “a” because it has not meaning when looking at the class definition.  So to abide by the 3rd party JSON contract, yet give others a meaningful property name, I decided to use the DataContractJsonSerializer.  Below I give a simple example of pretend response JSON from some 3rd party vendor JSON API (let’s prettend a=auth token value, exp=expiration in seconds, and sid=social security ID).

Basic JSON structure from the 3rd party response:

{ 
"token": {
"a":"…",
"exp":"123456789",
"sid":"…"
}
}
Using JavaScriptSerializer
public class Token
{
public string a;
public int epx;
public string sid;
}

public class TokenResponse
{
public token;
}

//
// code to receive and deserialize token class from some web response
//
string json = ...; // our json data from the 3rd party

// create serializer
JavaScriptSerializer serializer = new JavaScriptSerializer();
// return the deserialized object
return serializer.Deserialize<TokenResponse>(json);
This is a very simplified psuedo code, but the the key points are the simplicity of deserializing the response and the field names.  It’s only 2 lines of code to deserialize object!, but using the JsonScriptSerializer does not allow us to modify the field names.  If this class was confined to some class or method only, I’d go for the simplicity of this approach.  On the other hand, if this is some response class that needs to be used throughout your application or used by other people, it would be really hard to understand the field/property names as they are.  For instance, what does the 3rd party’s “sid” mean, user security ID, user social security ID, server ID, who knows unless you have the API document right there where you looking at the code.  Let’s take a different approach with the DataContractJsonSerializer, and pretend that our token classes are exposed to a broader audience.
Using DataContractJsonSerializer
[DataContract(Name = "token")]
public class Token
{
[DataMember(Name = "a", IsRequired = true)]
public string Value;
[DataMember(Name = "exp", IsRequired = true)]
public int SecondsBeforeExpiration;
[DataMember(Name = "sid", IsRequired = true)]
public string SocialSecurityNumber;
}

[DataContract]
public class TokenResponse
{
[DataMember(Name = "token", IsRequired = true)]
public Token;
}

//
// code to receive and deserialize token class from some web response
//

string json = ...; // our json data from the 3rd party
// create stream to hold json data
using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
// create serializer
DataContractSerializer serializer = new DataContractSerializer(typeof(TokenResponse));

return serializer.ReadObject(ms) as TokenResponse;
}
Notice that there is a lot more annotating going on with our classes and we had to create a MemoryStream to pass to the serializer?  This isn’t that big of a deal, but it’s a bit heavy if you just need a quick JSON serialization/deserialization.  I think that’s why the ASP.NET MVC framework uses the JavaScriptSerializer.  One thing to note though, is that all the field actually have names that can be quickly understood, so that when your reading code or using intelliscence, you don’t have to question what a field/property is if a developer forgot to add commenting to it.

No comments: