Deserializing Derived Types with JSON.NET

If you’re using Json.NET to serialize objects which involve inheritance hierarchies, there’s a little issue you might run into.

Let’s say we have a class Person:

    public class Person
    {
        public string Name { get; set; }
    }

…and we also have another class Employee which derives from Person:

    public class Employee : Person
    {
        public decimal Salary { get; set; }
    }

Then I can write the following little Console Application (in which Json.NET is installed via NuGet):

            var employee = new Employee() { Name = "John", Salary = 1000m };

            var json = JsonConvert.SerializeObject(employee);

            var deserialized = JsonConvert.DeserializeObject<Person>(json);

We’re serializing an Employee (which derives from Person), and then deserializing into a Person (the base class). Due to polymorphism, we’d expect the result to hold a reference to an Employee instance complete with Salary. Alas, this is not the case:

json-derivedclasses-problem

As you can see, the result is actually of type Person, and the Salary goes missing in the deserialization.

Apparently the solution is to turn on Type Name Handling. The code is thus transformed:

            var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };

            var employee = new Employee() { Name = "John", Salary = 1000m };

            var json = JsonConvert.SerializeObject(employee, settings);

            var deserialized = JsonConvert.DeserializeObject<Person>(json, settings);

Once we create an instance of JsonDerializerSettings with TypeNameHandling turned on, we can pass that object as a paramater in the serialization/deserialization methods to obtain the correct result:

json-derivedclasses-solution

As you can see, the deserialized result is now an Employee, complete with Salary. You’ll also notice that the actual serialized JSON has changed: there is now type information in it, and that’s what allows the correct type to be deserialized.

So why is this functionality not enabled by default? I can only guess that it’s for performance reasons.

4 thoughts on “Deserializing Derived Types with JSON.NET”

Leave a Reply

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