Polymorphic serialization using Newton Json.NET in HttpContent

Imagine a quite common client-server application where server exposes REST methods and client communicates using HTTP requests. Requests and responses are serialized in JSON format. There might be a problem if you try to send and receive a DTO that contains a collection of interfaces or abstract classes. I will talk about usage of Web API and Newton Json.NET as it’s underlying serialization library.

For example we have the following interface and some implementations of it:

interface IVehicle
{
    string Name { get; }
}
 
class Motorbike : IVehicle
{
    public string Name { getset; }
    public int MaxSpeed { getset; }
}
 
class Bus : IVehicle
{
    public string Name { getset; }
    public string Manufacturer { getset; }
    public int MaxPassengers { getset; }
}

The DTO looks like

class AvailableVehiclesDto
{
    public List<IVehicleVehicles { getset; }
}

Server sends a collection of vehicles to the client:

[HttpGet]
public HttpResponseMessage GetAvailableVehicles()
{
    var dto = new AvailableVehiclesDto
    {
        Vehicles = new List<IVehicle>
        {
            new Motorbike
            {
                Name = "Ural",
                MaxSpeed = 160
            },
            new Motorbike
            {
                Name = "Harley-Davidson Hummer",
                MaxSpeed = 80
            },
            new Bus
            {
                Name = "Ikarus 280",
                Manufacturer = "Ikarus",
                MaxPassengers = 180
            }
        }
    };
 
    return Request.CreateResponse(HttpStatusCode.OK, dto);
}

On the client side we try to get and deserialize the response:

var response = await _serviceClient.GetAsync(
    "http://Kirill-PC:9001/Resources/api/Vehicles/GetAvailableVehicles");
response.EnsureSuccessStatusCode();
var dto = await response.Content.ReadAsAsync<AvailableVehiclesDto>();

But the client will throw an exception JsonSerializationException during deserialization of the collection with the message:

Additional information: Could not create an instance of type IVehicle.
Type is an interface or abstract class and cannot be instantiated.

The problem is that client doesn’t know what was the initial type of each vehicle before serialization. The JSON of the collection above looks like:

{
    "Vehicles" : [
        {
            "Name" : "Ural",
            "MaxSpeed" : 160
        },
        {
            "Name" : "Harley-Davidson Hummer",
            "MaxSpeed" : 80
        },
        {
            "Name" : "Ikarus 280",
            "Manufacturer" : "Ikarus",
            "MaxPassengers" : 180
        }
    ]
}

This JSON doesn’t contain any information about the type of each collection object. In order to solve the issue, JSON formatters should be additionally configured on the client and server sides. The server side:

var config = new HttpConfiguration();
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling =
    TypeNameHandling.Auto;
return Request.CreateResponse(HttpStatusCode.OKdto, config);

The client side:

var response = await _serviceClient.GetAsync(
    "http://Kirill-PC:9001/Resources/api/Vehicles/GetAvailableVehicles");
response.EnsureSuccessStatusCode();
var formatter = new JsonMediaTypeFormatter
{
    SerializerSettings = { TypeNameHandling = TypeNameHandling.Auto }
};
var dto = await response.Content.ReadAsAsync<AvailableVehiclesDto>(
    new List<MediaTypeFormatter> { formatter });

After these changes the JSON looks like:

{
    "Vehicles" : [
        {
            "$type" : "DemoApp.Motorbike",
            "Name" : "Ural",
            "MaxSpeed" : 160
        },
        {
            "$type" : "DemoApp.Motorbike",
            "Name" : "Harley-Davidson Hummer",
            "MaxSpeed" : 80
        },
        {
            "$type" : "DemoApp.Bus",
            "Name" : "Ikarus 280",
            "Manufacturer" : "Ikarus",
            "MaxPassengers" : 180
        }
    ]
}

From now server adds a type field and client can deserialize DTO correctly.

4 thoughts on “Polymorphic serialization using Newton Json.NET in HttpContent

  1. Hi, great post, but I’m still getting the exception : “Could not create an instance of type SharedItems.Models.Layout.IVehicle. Type is an interface or abstract class and cannot be instantiated. Path ‘Vehicles[0].Name’, line 1, position 21.”

    Client:
    var response = await client.GetAsync(theUrl);
    response.EnsureSuccessStatusCode();
    var formatter = new JsonMediaTypeFormatter
    {
    SerializerSettings = { TypeNameHandling = TypeNameHandling.Auto }
    };
    var dto = await response.Content.ReadAsAsync(
    new List { formatter });

    Server:
    [HttpGet]
    public HttpResponseMessage GetLayouts()
    {
    var dto = new AvailableVehiclesDto
    {
    Vehicles = new List
    {
    new Motorbike
    {
    Name = “Ural”,
    MaxSpeed = 160
    },
    new Motorbike
    {
    Name = “Harley-Davidson Hummer”,
    MaxSpeed = 80
    },
    new Bus
    {
    Name = “Ikarus 280”,
    Manufacturer = “Ikarus”,
    MaxPassengers = 180
    }
    }
    };

    var config = new HttpConfiguration();
    config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling =
    TypeNameHandling.Auto;
    return Request.CreateResponse(HttpStatusCode.OK, dto, config);

    }

      1. Thank You for Your Suggestion, I’ve checked it out, the types in JSON are not set. But I’m using JsonFormatter when creating response

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s