A Custom Converter for Json.NET

I was playing around with Json.NET while trying to move some data back and forth between .NET and Flex. I found that I needed to deserialize a string that looks something like:

string json = @"{param1:{FirstName:'Jay',Age:2},param2:{FirstName:'Ray',Age:3}}";

where param1 and param2 are parameters to a method that I want to invoke as a remote service. I have two objects that I want to deserialize within a container object (the outer { }). I really don’t care about the container object but I have no way to tell Json.NET to ignore it. I have to have a real concrete to deserialize the container. I didn’t want to create specific objects for each call being made (there could be a lot) so I created a simple generic object that looks something like the following (error handling removed for clarity):

public class ParameterCollection
{
private readonly Dictionary<string, object> parameters;

internal ParameterCollection(Dictionary<string, object> parameters)
{
this.parameters = parameters;
}

public object this[string name]
{
get { return parameters[name]; }
}

public int Count
{
get { return parameters.Count; }
}
}

In order to deserialize to a ParameterCollection object, I needed to create a converter class that inherits from JsonConverter. It ended up looking like the following (error handling removed for clarity):

public class ParameterCollectionJsonConverter : JsonConverter
{
private readonly Type[] parameterTypes;
private readonly Dictionary<string, object> parameterInstances;

public ParameterCollectionJsonConverter(params Type[] parameterTypes)
{
this.parameterTypes = parameterTypes;
this.parameterInstances = new Dictionary<string, object>(parameterTypes.Length);
}

public override bool CanConvert(Type objectType)
{
return objectType.IsAssignableFrom(typeof(ParameterCollection));
}

public override object ReadJson(JsonReader reader, Type objectType)
{
reader.Read(); // read past start object token

for (int i = 0; i < parameterTypes.Length; i++)
{
string parameterName = reader.Value as string;

this.parameterInstances.Add(parameterName, new JsonSerializer().Deserialize(reader, parameterTypes[i]));
reader.Read();// read past end object token
}

reader.Read();// read past end object token

return new ParameterCollection(parameterInstances);
}

public static ParameterCollection Deserialize(TextReader jsonTextReader, params Type[] types)
{
JsonSerializer serializer = new JsonSerializer();
serializer.Converters.Add(new ParameterCollectionJsonConverter(types));

JsonReader reader = new JsonReader(jsonTextReader);
return serializer.Deserialize(reader, typeof(ParameterCollection)) as ParameterCollection;
}
}

So now I can deserialize to a ParameterCollection by passing in the types of each parameter like so:

TextReader tr = new StringReader(@"{param1:{FirstName:'Jay',Age:2},param2:{FirstName:'Ray',Age:3}}");

ParameterCollection paramCollection = ParameterCollectionJsonConverter.Deserialize(tr, typeof(SomeObject), typeof(SomeObject));

SomeObject someObj1 = paramCollection["param1"] as SomeObject;

I’m sure as soon as I post this somebody will let me know of a built-in way to do the same thing. ;)

Technorati Tags: ,,

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Ray Houston

Ray is a software development leader and architect with 20 years hands-on experience. He enjoys finding elegant solutions to complex problems and delivering real value to customers. Ray is a speaker and contributor to community events.
This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

8 Responses to A Custom Converter for Json.NET

  1. Scott says:

    Hi Ray,

    The .NET framework has two separate classes for serializing/deserializing Javascript objects. Have you tried either of those?

    System.Web.Script.Serialization.JavaScriptSerializer
    http://msdn2.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx
    It’s marked as “obsolete”, but I’ve heard rumors that it isn’t going anywhere in the framework.

    System.Runtime.Serialization.Json.DataContractJsonSerializer
    http://msdn2.microsoft.com/en-us/library/system.runtime.serialization.json.aspx

    DataContractJsonSerializer is part of the Indigo/WCF namespace.

  2. Ray Houston says:

    @Scott – thanks for the heads up! I’ll try the DataContractJsonSerializer in the future. Right now, our project is still in 2.0, but we will be moving to 3.5 soon. I was using the serializer in ASP.NET AJAX for 2.0 with web services, but I needed a different way to handle errors because Flex wasn’t playing nice. Since I’m not using ASP.NET web services anymore, I thought I’d try a lib that just had what I need in it.

  3. Chad Myers says:

    @Ray:

    Try those first. If you don’t have luck, I wrote a quick and dirty test using JScript.NET (Yes, trust me, it rocks — just a few lines to do JSON [de]serialization) and it was at least twice as fast as that code you posted.

  4. Ray Houston says:

    @Chad – really? Can you post some code? Does it run in 2.0?

  5. Chad Myers says:

    @Ray: Yes, JScript.NET doesn’t appear to have been touched in .NET 3.5 (since 3.5 is mostly C#/VB compiler extensions + libs, no CLR/CLI changes).

    I’m workin’ on getting the code packaged up

  6. Jay Brownlee says:

    @Chad: I’d like to see that JScript.NET code for doing JSON [de]serialization. When (if) you get some time away from your new job can you post it?

  7. Jim Bent says:

    Thank you for sharing such a good thing.
    I am also playing JSON.NET1.3 for ajax grid data feed, but I can’t get it work. Are you using JSON.NET2.0?

  8. Ray Houston says:

    @Jim – No, I haven’t tried JSON.NET 2.0 yet.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>