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?
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).
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.
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.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With