Click here to Skip to main content
Click here to Skip to main content

The ASP.NET AJAX Serialization Process

, 10 Dec 2007 CPOL
Rate this:
Please Sign up or sign in to vote.
Understand how the ASP.NET AJAX serialization process works and how you can leverage the advantages of JSON serialized text.

Introduction

In this article, we’ll examine the ASP.NET AJAX serialization process. We will examine the server-side methods and client-side methods which serialize and deserialize objects.

What is JavaScript Object Notation (JSON)?

JavaScript Object Notation or JSON provides a more efficient means of transferring data than previously found with XML and SOAP. JSON is a means of serializing an object into a lightweight string that can be sent across the wire. For example, consider the following C# class:

public class User
{
    string FirstName;
    string LastName;
}

Now, consider an instance of the object as follows:

User usr = new User();
usr.FirstName = "John"
usr.LastName = "Smith";

When serialized into JSON formatted text, we’ll be left with the following:

{ FirstName : "John"
LastName : "Smith" }

From within JavaScript, we can deserialize the JSON text string into an object using the JavaScript supplied method eval() or the class Sys.Serialization.JavaScriptSerializer. Using the AJAX class, we can also serialize a JavaScript object to be sent to the server. We can then use the server-side object JavaScriptSerializer to deserialize the JSON text string object, as we will discover in this article.

Getting Dirty

The object responsible for serialization/deserialization is JavaScriptSerializer. The relevant members of this object can be seen below.

public class JavaScriptSerializer
{
    // Fields

    internal const int DefaultMaxJsonLength = 0x200000;
    internal const int DefaultRecursionLimit = 100;
    internal const string ServerTypeFieldName = "__type";

    // Methods

    static JavaScriptSerializer();
    public JavaScriptSerializer();
    public JavaScriptSerializer(JavaScriptTypeResolver resolver);
    public T ConvertToType<t />(object obj);
    public T Deserialize<t />(string input);
    public object DeserializeObject(string input);
    public void RegisterConverters(IEnumerable<javascriptconverter /> converters);
    public string Serialize(object obj);
    public void Serialize(object obj, StringBuilder output);

    // Properties

    public int MaxJsonLength { get; set; }
    public int RecursionLimit { get; set; }
    internal JavaScriptTypeResolver TypeResolver { get; }
}

First off, the serialization process will fail if the number of nested objects is greater than that defined within the RecursionLimit property. That said; note the default recursion limit of 100. The serialization process will also fail if the length of the serialized text is greater than that of the MaxJsonLength property; again, note the default value of 2,097,152 base ten.

The object is serialized into a StringBuilder object; after the serialization completes, the string representation will be returned. The majority of the action happens within the private SerializeValue() method. Before we examine this method, it’s worth noting that the JavaScriptSerializer object may make use of JavaScriptTypeResolver, which is used to resolve a type from a string and vice versa, which is important when custom objects are serialized. The __type attribute will be included within the JSON serialized text, hence indicating the object type. The client will then deserialize the JSON text into an object and populate the indicated properties with the values found within the JSON serialized text.

The JavaScriptTypeResolver object includes two public methods, one to resolve the type to string, and the other from string to type. The class prototype is as follows:

public abstract class JavaScriptTypeResolver
{
    // Methods

    protected JavaScriptTypeResolver();
    public abstract Type ResolveType(string id);
    public abstract string ResolveTypeId(Type type);
}

The JavaScriptTypeResolver class is a base abstract class, and should be implemented by another object which can be used to resolve the type to string and vice versa. The object which we may use is the SimpleTypeResolver, and implements the above methods exactly as expected – making use of the System.Type object to resolve either a string representation into a valid Type object or a valid Type object into a string representation. See below.

public override Type ResolveType(string id)
{
    return Type.GetType(id);
}

public override string ResolveTypeId(Type type)
{
    if (type == null)
    {
        throw new ArgumentNullException("type");
    }
    return type.AssemblyQualifiedName;
}

Finally, the JavaScriptSerializer object may also make use of a JavaScriptConverter object as the internal serialization process is not capable of serializing all available data types, in which case, an object can inherit from the base abstract JavaScriptConverter object and implement the serialization/deseralization process for specific data types. A converter object may be registered with the JavaScriptSerializer using the RegisterConverters() method which stores all converter objects in a Dictionary object, as multiple converters may be registered for different data types. The Dictionary object is defined as follows:

this._converters = new Dictionary<type, >();

That is, the Type of the object is the key, while the value is an instance of a JavaScriptConverter object to use for the associated data type.

The SerializeValue() method will check if a custom converter object exists for the data type which should be serialized; if one exists, it will make use of the custom converter object to serialize/deserialize the object; otherwise, an internal serialization method will be used, which is also determined based on the object's data type. The method SerializeValueInternal() will be invoked and will serialize the data types as described in the table below:

Table 1 – Serialization of data types
Data type Serialized as
null or DBNull "null"
string Quoted string
char If ‘\0’, "null". Else serialized as a quoted string.
bool "true" or "false"
DateTime "\/Date (ticks since 12:00AM 1970/01/01 UTC)\/"
Guid “string representation”: sb.Append("\"").Append(guid.ToString()).Append("\"");
Uri sb.Append("\"").Append(uri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped)).Append("\"");
double sb.Append(((double) o).ToString("r", CultureInfo.InvariantCulture));
float sb.Append(((float) o).ToString("r", CultureInfo.InvariantCulture));
primitive or decimal

IConvertible convertible = o as IConvertible;

sb.Append(convertible.ToString(CultureInfo.InvariantCulture));

Enum sb.Append((int) o);
IDictionary

JSON text, for example.

{"Key1":Value1,"Key2":Value2 ... }

IEnumerable

JSON text, for example.

{"Key1":Value1,"Key2":Value2 ... }

A custom object is serialized similar to an IDictionary, with a few differences. If a JavaScriptTypeResolver object has been defined, the object type will be converted to a string, and the object definition will include the string literal __type followed by the string representation of the object data type. The remaining object properties and fields are obtained by looping the fields and properties obtained from the Type object. All fields and properties which have been defined as public and do not include the metadata ScriptIgnoreAttribute property will be included within the JSON object representation of the object.

Let us now examine the serialization process by way of an example object. Considering the objects defined below.

public class Customer
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set { _firstName = value; }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set { _lastName = value; }
    }

    private string _email;
    public string EmailAddress
    {
        get { return _email; }
        set { _email = value; }
    }

    private Phone _phoneNumber;
    public Phone PhoneNumbers
    {
        get { return _phoneNumber; }
        set { _phoneNumber = value; }
    }

}

public class Phone
{
    private string _homePhone;
    public string HomePhone
    {
        get { return _homePhone; }
        set { _homePhone = value; }
    }

    private string _workPhone;
    public string WorkPhone
    {
        get { return _workPhone; }
        set { _workPhone = value; }
    }
}

If this object were returned from a Web Service method, the object would be serialized automatically from within the InvokeMethod() of the RestHandler. However, in the sample case above, we’re making use of these objects from within our Page.Page_Load() method, hence we should create the objects and serialize them automatically using the JavaScriptSerializer object previously examined. Consider the following code to serialize an object:

JavaScriptSerializer jsSerializer = 
   new JavaScriptSerializer(new SimpleTypeResolver());
Customer cust = new Customer();
cust.FirstName = "Joe";
cust.EmailAddress = "jknown@domain.com";
cust.PhoneNumbers = new Phone();
cust.PhoneNumbers.HomePhone = "888-888-8888";

string serializedText = jsSerializer.Serialize(cust);

Notice that the JavaScriptSerializer object has been initialized with the SimpleTypeResolver which, as you know, will be invoked to evaluate the type of the serialized object to a string. The serialized JSON text is shown below:

{"__type":"Customer, App_Web_plrzlwbj,
Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null","FirstName":"Joe","LastName":null,
"EmailAddress":jknown@domain.com,
"PhoneNumbers":{"__type":"Phone, App_Web_plrzlwbj, Version=0.0.0.0, 
Culture=neutral, PublicKeyToken=null",
"HomePhone":"888-888-8888","WorkPhone":null}} 

Notice that the PhoneNumbers property is of the custom type Phone, hence when serialized, the value of the PhoneNumbers property will be a JSON object, which is the serialized version of the Phone object. Again, notice the type is identified, which is used when deserializing so that the correct object may be created and populated. That said, let us now examine the deserialization process.

The deserialization process is performed using the JavaScriptObjectDeserializer object, which when an instance is created, the JSON text string should be supplied as a parameter to the constructor. After an instance has been created, we may invoke the DeserializeInternal() method. Here, the JSON serialized string will be parsed, and the appropriate objects matching the serialized version will be created and populated.

To deserialize a JSON string, we may invoke the Deserialize() method of the JavaScriptSerializer object. The return value being an instance of the initial object with the properties defined to the previously specified values. Consider the code below:

Customer cust = jsSerializer.Deserialize<customer>(serializedText);

Conclusion

That’s all there really is to it. We should now have a basic understanding of how the AJAX JSON serialization/deserialization process works, and how we can leverage JSON serialization for use within our AJAX code. The process is really quite simple.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Matthew Ellis
Technical Writer Magma Interactive, LLC
United States United States

Matthew Ellis has been involved in the programming industry for many years and has a vast knowledge in C/C++ and C#. He began his technical journey at the very early age of 9 when he first began developing in the C programming language. Matthew has also been involved in the game development industry where he wrote the book titled Direct3D Primer, which shipped as part of another title.

Matthew, as of recently, has been doing consulting work for companies abroad where he develops unified systems bringing together the latest in technologies. He develops applications in the C# and C++ programming languages. He develops ASP.NET front end applications and numerous C++ based applications for use across a variety of different platforms.

Matthew's latest book titled ASP.NET AJAX Programming Tricks was released October 30, 2007 and was published by Magma Interactive, LLC.

You can check out ASP.NET AJAX Programming Tricks here.

The E-Book Edition is available here.


Comments and Discussions

 
QuestionWhat about the XML serialization? Pinmemberfergara23-Oct-09 9:08 

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 | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 10 Dec 2007
Article Copyright 2007 by Matthew Ellis
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid