Click here to Skip to main content
15,883,883 members
Articles / Programming Languages / C#
Tip/Trick

Serialize and Deserialize Classes with Interface Properties with JSON.NET

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
5 Sep 2016CPOL2 min read 50.6K   3   5   3
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:

JavaScript
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:

JavaScript
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:

JavaScript
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:

JavaScript
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:

JavaScript
{
  "$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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Ireland Ireland
Summary
I am an Informatics Engineer with a University Degree in Informatics Engineering and a PhD in Information Engineering.
I have more than 9 years of working experience ICT (from Development to Team Leader) with and In-depth technical / IT know-how.
Practical competences in development, analysis and project management in terms of coordination and content.

Keywords / Skill Set
C# 7.0, NET Core, ASP NET Core, EF Core; HTML(5), CSS(3), Typescript, JavaScript, jQuery,Telerik Kendo, AngularJS, SignalR; MVC, MVVM; SQL, T-SQL, Sql Server; Azure cloud based services, Amazon Web Services
Relevant Web Applications / Tools:
Visual Studio 2017, SQL Server 2016; TFS, Git

Languages: Italian (mother tongue), English (fluent).

Education:

1998 – 2004, University Of Siena (IT), Tuscany

BSc in Informatics Engineering

2004 – 2007, Superior School of Doctorate, University of Siena (IT), Tuscany

PhD in Information Engineering

Comments and Discussions

 
QuestionWhat happens in a heterogenous environment? Pin
Klaus Luedenscheidt5-Sep-16 18:41
Klaus Luedenscheidt5-Sep-16 18:41 
AnswerRe: What happens in a heterogenous environment? Pin
Jono Stewart5-Sep-16 20:37
Jono Stewart5-Sep-16 20:37 
AnswerRe: What happens in a heterogenous environment? Pin
Aless Alessio6-Sep-16 3:33
Aless Alessio6-Sep-16 3:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.