Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Json.NET converters to deserialize properties

I have a class definition that contains a property that returns an interface.

public class Foo {      public int Number { get; set; }      public ISomething Thing { get; set; } } 

Attempting to serialize the Foo class using Json.NET gives me an error message like, "Could not create an instance of type 'ISomething'. ISomething may be an interface or abstract class."

Is there a Json.NET attribute or converter that would let me specify a concrete Something class to use during deserialization?

like image 427
dthrasher Avatar asked Feb 12 '10 20:02

dthrasher


People also ask

What is JSON deserialization?

JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).

What is a JSON converter?

A converter is a class that converts an object or a value to and from JSON. The System. Text. Json namespace has built-in converters for most primitive types that map to JavaScript primitives.

How does JSON deserialization work?

In Deserialization, it does the opposite of Serialization which means it converts JSON string to custom . Net object. In the following code, it creates a JavaScriptSerializer instance and calls Deserialize() by passing JSON data. It returns a custom object (BlogSites) from JSON data.

Is Newtonsoft JSON obsolete?

Yet Newtonsoft. Json was basically scrapped by Microsoft with the coming of . NET Core 3.0 in favor of its newer offering designed for better performance, System.


2 Answers

One of the things you can do with Json.NET is:

var settings = new JsonSerializerSettings(); settings.TypeNameHandling = TypeNameHandling.Objects;  JsonConvert.SerializeObject(entity, Formatting.Indented, settings); 

The TypeNameHandling flag will add a $type property to the JSON, 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. The $type will be a fully-qualified type, so if you're serializing it with type info,, the deserializer needs to be able to understand it as well.

Documentation: Serialization Settings with Json.NET

like image 99
Daniel T. Avatar answered Oct 05 '22 03:10

Daniel T.


You can achieve this through the use of the JsonConverter class. Suppose you have a class with an interface property;

public class Organisation {   public string Name { get; set; }    [JsonConverter(typeof(TycoonConverter))]   public IPerson Owner { get; set; } }  public interface IPerson {   string Name { get; set; } }  public class Tycoon : IPerson {   public string Name { get; set; } } 

Your JsonConverter is responsible for serializing and de-serializing the underlying property;

public class TycoonConverter : JsonConverter {   public override bool CanConvert(Type objectType)   {     return (objectType == typeof(IPerson));   }    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)   {     return serializer.Deserialize<Tycoon>(reader);   }    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)   {     // Left as an exercise to the reader :)     throw new NotImplementedException();   } } 

When you work with an Organisation deserialized via Json.Net the underlying IPerson for the Owner property will be of type Tycoon.

like image 20
MrMDavidson Avatar answered Oct 05 '22 03:10

MrMDavidson