Keyvan Nayyeri

God breathing through me

Custom JSON Serialization in ASP.NET AJAX

As you would already know, JSON serialization of server objects is an inherent task in ASP.NET AJAX workflow, and plays the key role in developing AJAX applications. However, default JavaScriptSerlializer included in ASP.NET AJAX framework has some restrictions for specific classes and you encounter problems when using this default serializer. The solution is, extending the serializer with your own converters that target these specific types.

Fortunately there is a simple and easy to develop extensibility point in ASP.NET AJAX that allows you to do this, and in this post I want to walk through an example that covers this topic.

In order to extend ASP.NET AJAX to be able to serialize your objects in JSON format, you can derive from JavaScriptConverter abstract base class located in System.Web.Script.Serialization namespace which has two methods and one property to override:

  • SupportedTypes: Returns an IEnumerable collection of types that can be serialized/deserialized by this custom converter.
  • Serialize: Gets an object as well as a JavaScriptSerializer instance, and serializes the object in a dictionary of string keys and their corresponding values then returns the result.
  • Deserialize: Gets a dictionary of string keys and object values, the type of object, and a JavaScriptSerializer instance, and deserializes the data in dictionary to the original type.

Giving an example would be enough to show how to use these three methods to serialize/deserialize your objects with custom converter, so here I give a simple example to clarify this process. In this example, I develop a BookConverter class that serializes and serializes objects of a custom class type called Book which represents a book title.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

 

namespace JSONSerializerSample.Code

{

    public class Book

    {

        public string Title { get; set; }

 

        public string Author { get; set; }

 

        public string Isbn11 { get; set; }

 

        public string Isbn13 { get; set; }

    }

}

To develop my own custom serializer, I create a class called BookConverter and derive it from the abstract JavaScriptConverter class.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Script.Serialization;

using JSONSerializerSample.Code;

 

namespace JSONSerializerSample.Jason

{

    public class BookConverter : JavaScriptConverter

    {

        public override IEnumerable<Type> SupportedTypes

        {

            get { throw new NotImplementedException(); }

        }

 

        public override IDictionary<string, object> Serialize(object obj,

            JavaScriptSerializer serializer)

        {

            throw new NotImplementedException();

        }

 

        public override object Deserialize(IDictionary<string, object> dictionary,

            Type type, JavaScriptSerializer serializer)

        {

            throw new NotImplementedException();

        }

    }

}

Now I begin developing each of these three main elements.

SupportedTypes property is a read only property that must return a collection of supported types by the converter, so there isn’t any special point to discuss about it. For my example I just need to return one type which is Book.

public override IEnumerable<Type> SupportedTypes

{

    get { return new List<Type>(new Type[] { typeof(Book) }); }

}

The first method to override is Serialize which manages the serialization process, and must return an IDictionary of string keys with object values that represent the serialized form of the object types in JSON format.

public override IDictionary<string, object> Serialize(object obj,

    JavaScriptSerializer serializer)

{

    Book book = obj as Book;

    Dictionary<string, object> result = new Dictionary<string, object>();

 

    if (book != null)

    {

        result.Add("title", book.Title);

        result.Add("author", book.Author);

        result.Add("isbn11", book.Isbn11);

        result.Add("isbn13", book.Isbn13);

 

        return result;

    }

 

    return result;

}

As you see, I created a dictionary object and added my properties with appropriate string keys to this dictionary then returned the final result.

The second function is Deserialize which gets the dictionary of values along the type of objects and a JavaScriptSerializer, and returns an object that is deserialized.

public override object Deserialize(IDictionary<string, object> dictionary,

    Type type, JavaScriptSerializer serializer)

{

    if ((dictionary != null) && (type == typeof(Book)))

    {

        Book book = new Book();

 

        book.Title = serializer.ConvertToType<string>(dictionary["title"]);

        book.Author = serializer.ConvertToType<string>(dictionary["author"]);

        book.Isbn11 = serializer.ConvertToType<string>(dictionary["isbn11"]);

        book.Isbn13 = serializer.ConvertToType<string>(dictionary["isbn13"]);

 

        return book;

    }

 

    return null;

}

Here I create an instance of the book object and retrieve appropriate properties for this object from the dictionary then return the deserialized object. Just note the way that I used my JavaScriptSerializer instance to deserialized other types.

After implementing the converter, you must declare it in Web.Config to allow ASP.NET AJAX to use this converter in order to serialize/deserialize your types. To do this, you need to add a <jsonSerialization /> element within <webServices/ > within <scripting /> which is a sub-element of <system.web.extensions />. <jsonSerialization /> helps you override the default behavior of ASP.NET AJAX JSON converter, so you can add a <converters /> sub-element inside this element and set the name and type of your custom converter to be used.

<system.web.extensions>

  <scripting>

    <webServices>

      <jsonSerialization maxJsonLength="1000">

        <converters>

          <add name="BookConverter" type="JSONSerializerSample.Jason.BookConverter, JSONSerializerSample" />

        </converters>

      </jsonSerialization>

    </webServices>

  </scripting>

</system.web.extensions>

I have published the source code sample for this post as a download package.

7 Comments

Elijah Manor
Nov 11, 2008 11:46 PM
#

I have yet had to make my own serializer for JavaScript, but I have heard that some others have had some problems with the default implementation in ASP.NET. Thanks for your blog post, it will definitely come in handy when I need to customize my own.

Pingback from Dew Drop - November 12, 2008 | Alvin Ashcraft's Morning Dew


Jahedur Rahman
Nov 12, 2008 9:39 AM
#

Hello,

Nice post.

Original source code is showing:

public override object Deserialize(IDictionary<string, object> dictionary,

Type type, JavaScriptSerializer serializer)

{

if ((dictionary != null) && (type == typeof(Book)))

{

Book book = new Book();

book.Title = serializer.ConvertToType<string>(dictionary["title"]);

book.Author = serializer.ConvertToType<string>(dictionary["author"]);

book.Isbn11 = serializer.ConvertToType<string>(dictionary["isbn11"]);

book.Isbn13 = serializer.ConvertToType<string>(dictionary["isbn13"]);

return book;

}

return null;

}

Mistake???


Keyvan Nayyeri
Nov 12, 2008 9:40 AM
#

@Jahedur

Which mistake?!


Jahedur Rahman
Nov 12, 2008 10:15 AM
#

In the post you wrote:

book.Title = (string)dictionary["title"];

book.Author = (string)dictionary["author"];

book.Isbn11 = (string)dictionary["isbn11"];

book.Isbn13 = (string)dictionary["isbn13"];

got it?


Keyvan Nayyeri
Nov 12, 2008 10:33 AM
#

@Jahedur

Aha! Somewhere at the middle I changed my mind to use the JavaScriptSerializer approach to better showcase the development process but forgot to use it in my post text. Now post is updated with the actual code.

By the way, for string type both approaches work without problems.

Thank you for pointing this :-)


David
Jan 06, 2009 1:00 AM
#

Thanks for the great example!

Leave a Comment





Ads Powered by Lake Quincy Media Network