Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Serialize and Deserialize Classes with Interface Properties with JSON.NET

0.00/5 (No votes)
5 Sep 2016 1  
Serialize concrete classes that have interface properties

Introduction

If you have to deserialize a JSON stream into a concrete class that has interface properties, Json.NET helps you to serialize the object adding a $type property to the JSON, which allows him to know which concrete type it needs to deserialize the object into.

Using the Code

I have been facing the same problem these days, and I came to this easy, fast and readable solution:

Let's say that we use Json.NET to serialize/deserialize objects sent-to/received-from a Web Service, and we want to serialize/deserialize classes that have interface properties.

Serializing will give us no issues (using the standard settings), but when we will try to deserialize the model, we will get the following error:

Quote:

Could not create an instance of type Namespace.Intarface. Type is an interface or abstract class and cannot be instantiated.

  • Serializing a class that implements an interface is simple.
  • Deserializing JSON to one of many possible classes that implement an interface is not.
  • Json.NET allows us to solve this problem by simply adding an extra settings during the serialization process.

We just need to add an extra setting during the serialization:

var indented = Formatting.Indented;
var settings = new JsonSerializerSettings()
{
      TypeNameHandling = TypeNameHandling.All
};
string serialized = JsonConvert.SerializeObject(wizardConf, indented, settings);

And then apply the same setting during the deserialization:

var settings = new JsonSerializerSettings()
{
      TypeNameHandling = TypeNameHandling.All
};
YourObject obj =  JsonConvert.DeserializeObject<yourobject>(JsonString, settings);

So, let's say we got to serialize an object containing two list of Interfaces:

public class Class1 : IInterface1
{
   public void method1()
   {
       // whatever1
   }
}
 
public class Class2 : IInterface2
{
   public void method2()
   {
       // whatever2
   }
}
 
   public class ObjToSerialize
   {
       public List<IInterface1> list1;
       public List<IInterface2> list2;
 
       public ObjToSerialize()
       {
           list1 = new List<IInterface1>();
           list2 = new List<IInterface2>();
       }
   }

And at runtime, we added one object to each list:

ObjToSerialize obj = new ObjToSerialize();
obj.list1.Add(new Class1());
obj.list2.Add(new Class2());

By adding the TypeNameHandling flag, the serialized class will appear as follows:

{
  "$type": "Namespace.ObjToSerialize, AssemblyName",
  "list1": {
    "$type": "System.Collections.Generic.List`1[[Namespace.IInterface1, AssemblyName]], mscorlib",
    "$values": [
      {
        "$type": "Namespace.Class1, AssemblyName"
      }
    ]
  },
  "list2": {
    "$type": "System.Collections.Generic.List`1[[Namespace.IInterface2, AssemblyName]], mscorlib",
    "$values": [
      {
        "$type": "Namespace.Class2, AssemblyName"
      }
    ]
  }
}

The resulting JSON file basically tells everything we need to know.
It says that the ObjToSerialize contains two properties, each of them is a List of Interfaces, whose implementation is Class1 in the first case and Class2 in the second case.

The deserializer will take this string and easily reconstruct the object as it has all the details of the interface implementation.

Quote:

The TypeNameHandling flag adds a $type property to the JSON.

The $type is a fully-qualified type which allows Json.NET to know which concrete type it needs to deserialize the object into. This allows you to deserialize an object while still fulfilling an interface or abstract base class.

The downside, however, is that this is very Json.NET-specific.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here