CTS – Your Technology Partner

Accepting Schema-Less data with Json.NET using JsonExtensionData

Written by Lydon Bergin on May 27, 2014

Recently I was faced with an interesting requirement while working on a Web Service API. The web service needed to accept JSON data via POST and PUT requests, and persist the data to database tables using simple insert and update statements – fairly standard REST API functionality. The interesting part is that the web service needed to be able to accept both data that was a part of the underlying schema, as well as accept and persist extended (or schema-less) data during the the deserialization step handled by the Json.NET library.

After researching the possibilities and digging through the Json.NET source code (available on GitHub), I found a barely documented feature of the Json.NET library that quickly and easily handled the exact requirement I was facing! This feature is simply and elegantly implemented as a property attribute called JsonExtensionData, and since it took me a while to figure out, I’ve written this blog post to easily show how to use it.

Example Schema

Our application will receive and deserialize JSON data into the following classes (the schema).

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Address Address { get; set; }
    [JsonExtensionData]
    public Dictionary<string, object> SchemaLessData { get; set; }
}

public class Address
{
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
    [JsonExtensionData]
    public Dictionary<string, object> SchemaLessData { get; set; }
}

NOTE: The [JsonExtensionData] attribute is part of the Newtonsoft JSON Library – in order for the above code sample to work, install Json.NET using the NuGet Package Manager, and add Newtonsoft.Json to your using statement.

Using the [JsonExtensionData] attribute, the Json.NET deserializer will automatically store incoming JSON data that doesn’t match our schema into the SchemaLessData property of our objects!

Input Data

Our application needs to receive the following JSON:

{
    ‘FirstName’: ‘Lydon’,
    ‘LastName’: ‘Bergin’,
    ‘Pronounciation’: ‘l IH d uh n’,
    ‘Employer’: ‘CTS, Inc.’,

    ‘Address’: {
        ‘AddressLine1’: ‘5000 Meridian Boulevard’,
        ‘AddressLine2’: ‘Suite 370’,
        ‘City’: ‘Franklin’,
        ‘State’: ‘TN’,
        ‘Zip’: ‘37067’,
        ‘Country’: ‘USA’,
        ‘CareOf’: ‘Lydon Bergin’

    }
}

Notice that the fields marked in bold do not match our defined schema, but our application will still accept and store this data into the SchemaLessData property of our objects.

Test It Out

The code below uses the Json.NET library to deserialize the JSON string to our schema objects:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Schema_LessJSON
{
    class Program
    {
        static void Main(string[] args)
        {
            string incomingJson =
                @”{
                    ‘FirstName’: ‘Lydon’,
                    ‘LastName’: ‘Bergin’,
                    ‘Pronounciation’: ‘l IH d uh n’,
                    ‘Employer’: ‘CTS, Inc.’,
                    ‘Address’: {
                        ‘AddressLine1’: ‘5000 Meridian Boulevard’,
                        ‘AddressLine2’: ‘Suite 370’,
                        ‘City’: ‘Franklin’,
                        ‘State’: ‘TN’,
                        ‘Zip’: ‘37067’,
                        ‘Country’: ‘USA’,
                        ‘CareOf’: ‘Lydon Bergin’
                        }
                    }”;

            Person p = JsonConvert.DeserializeObject<Person>(incomingJson);
        }
    }
}

As you can see in the figure below, the Json.NET library has inserted our external data into our Dictionary object, just like that!

image

Now that we have captured the data into a dictionary object, the possibilities are endless.  The Json.NET serializer also respects the JsonExtensionData attribute, so serializing our Person object back to a string results in the same string format.

Comments

comments