0

I'm trying to deserialize a json back to the object.
I have a List of interface in the object, which on deserializing is failing.
Pasting the code below.

Model

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public List<IAddress> Addresses { get; set; }
}

public abstract class IAddress
{
    public string HomeTown { get; set; }
}

public class Address : IAddress
{
    public string Location { get; set; }
    public string Street { get; set; }
    public string Zip { get; set; }
}

The code to serialize and deserialize are as follows:

var personObj = new Person
{
    Name = "John Doe",
    Age = 30,
    Addresses = new List<IAddress>
    {
        new Address
        {
            Location = "location1",
            Street = "Vzk",
            Zip = "686670"
        }
    }
};

var json = JsonConvert.SerializeObject(personObj);
System.Console.WriteLine(json);

/*
{
    "Name": "John Doe",
    "Age": 30,
    "Addresses": [{
        "Location": "location1",
        "Street": "Vzk",
        "Zip": "686670",
        "HomeTown": null
    }]
}
*/

var p2 = JsonConvert.DeserializeObject<Person>(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });

System.Console.WriteLine((p2.Addresses[0] as Address).Zip);

The error that I'm getting is:

Unhandled Exception: Newtonsoft.Json.JsonSerializationException: Could not create an instance of type Human.IAddress. Type is an interface or abstract class and cannot be instantiated. Path 'Addresses[0].Location', line 1, position 53. at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) at Parser.Program.Main(String[] args) in d:\expmts\csharp\Person\Parser\Program.cs:line 82

Is there any way to make NewtonSoft understand that, for type IAddress, Address is the type to be initiated.

Thanks in advance.

Fábio Nascimento
  • 2,644
  • 1
  • 21
  • 27
Alen Alex
  • 897
  • 4
  • 15
  • 31
  • 1
    maybe a douplicate of https://stackoverflow.com/questions/5780888/casting-interfaces-for-deserialization-in-json-net? – Malior Mar 27 '19 at 10:22
  • just change interface to class. Error contains all needed information – demo Mar 27 '19 at 10:23
  • Either all list items are of type `Employee` so you make it a `List`, or the list items can be of different types and then you need something in the serialised form to indicate the type of each item, i.e. the *discriminator* feature in the OpenAPI spec. – user247702 Mar 27 '19 at 10:25
  • This is a special use case, where I'm forced to do it this way due to compatibility issues. I have an option `[XmlInclude(typeof(Address)]` in case of `xml serialization`. What I'm looking for is something similar to it but in `json`. – Alen Alex Mar 27 '19 at 10:33

0 Answers0