Geeks With Blogs
The Reluctant Blogger Blogging not because I have to, but because I want to

I have to admit that I’m a basic user when it comes to JSON serialization/deserialization.  I’ve used JSON.NET and the DataContractJsonSerializer.  I’ve read that JSON.NET is faster and more efficient than the built-in .NET serializer, but I haven’t had to build a system that is dependent on squeezing microseconds out of my serialization routines.  That said, I do prefer JSON.NET because it is more flexible when it comes to using DataContractAttribute and DataMemberAttribute for customizing your JSON output.

So I came across an interesting question on StackOverflow today, asking how a json string like:

{‘one’: 1, ‘two’: 2, ‘three’: 3, ‘four’: 4, ‘blah’: 100}

would have its “one” and “two” properties deserialized to an object’s One and Two properties (easy) and anything else in the json string would be dumped into a Dictionary<string,object> (hmmm…not so easy).  So the resulting object would look like:

Mapped mappedObj = { 
  One = 1; 
  Two = 2; 
  TheRest = [{three=3}, {four=4}, {blah=100}]'; 
}

I’ve read about custom JSON.NET converters, but had never written one.  So I decided to give it a shot and discovered that it’s really not too bad.  Here’s my sample code:

using System;
using System.Collections.Generic;
using System.Linq;

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Reflection;

namespace JsonConverterTest1
{
    public class Mapped
    {
        private Dictionary<string, object> _theRest = new Dictionary<string, object>();
        public int One { get; set; }
        public int Two { get; set; }
        public Dictionary<string, object> TheRest { get { return _theRest; } }
    }

    public class MappedConverter : CustomCreationConverter<Mapped>
    {
        public override Mapped Create(Type objectType)
        {
            return new Mapped();
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var mappedObj = new Mapped();
            //get an array of the object's props so I can check if the JSON prop s/b mapped to it
            var objProps = objectType.GetProperties().Select(p => p.Name.ToLower()).ToArray();

            //loop through my JSON string
            while (reader.Read())
            {
                //if I'm at a property...
                if (reader.TokenType == JsonToken.PropertyName)
                {
                    //convert the property to lower case
                    string readerValue = reader.Value.ToString().ToLower();
                    if (reader.Read())  //read in the prop value
                    {
                        //is this a mapped prop?
                        if (objProps.Contains(readerValue))
                        {
                            //get the property info and set the Mapped object's property value
                            PropertyInfo pi = mappedObj.GetType().GetProperty(readerValue, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
                            var convertedValue = Convert.ChangeType(reader.Value, pi.PropertyType);
                            pi.SetValue(mappedObj, convertedValue, null);
                        }
                        else
                        {
                            //otherwise, stuff it into the Dictionary
                            mappedObj.TheRest.Add(readerValue, reader.Value);
                        }
                    }
                }
            }
            return mappedObj;
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            //a sample JSON string to deserialize
            string json = "{'one':1, 'two':2, 'three':3, 'four':4}";

            //call DeserializeObject, passing in my custom converter
            Mapped mappedObj = JsonConvert.DeserializeObject<Mapped>(json, new MappedConverter());

            //output some of the properties that were stuffed into the Dictionary
            Console.WriteLine(mappedObj.TheRest["three"].ToString());
            Console.WriteLine(mappedObj.TheRest["four"].ToString());
        }
    }
}

It’s pretty simple to create a custom converter and it’s almost limitless as to what you can do with it.

Of course, my sample code above is pretty simple and doesn’t take into account arrays or nested objects in the JSON string; but, that can be accounted for by using the JsonToken enumeration (which I do above in detecting a property) and checking for the start of a nested object or an array.

I found this an interesting exercise and gave me an opportunity to take a tour of a feature in JSON.NET that I’ve read about but never used.  I hope you find it interesting.

Posted on Tuesday, July 26, 2011 1:22 PM | Back to top


Comments on this post: JSON.NET Custom Converters–A Quick Tour

# re: JSON.NET Custom Converters–A Quick Tour
Requesting Gravatar...
Thank you very much for the article, it was of great help!
Left by Tero on Oct 22, 2013 4:57 AM

# re: JSON.NET Custom Converters–A Quick Tour
Requesting Gravatar...
Just FYI, this feature is now built into Json.Net. All you have to do is mark your Dictionary<string, object> with a [JsonExtensionData] attribute. See http://james.newtonking.com/archive/2013/05/08/json-net-5-0-release-5-defaultsettings-and-extension-data
Left by Brian on Jan 31, 2015 11:25 AM

# re: JSON.NET Custom Converters–A Quick Tour
Requesting Gravatar...
This is one of the best simple examples of this on the web, it really helped me get my head around writing my first converter!
Left by James on Feb 11, 2015 6:24 AM

Your comment:
 (will show your gravatar)


Copyright © David Hoerster | Powered by: GeeksWithBlogs.net | Join free