Deserialize a List<AbstractClass> with newtonsoft.json

.net, c#, json.net, serialization, vb.net

Solution

Make sure you specify TypeNameHandling when deserializing, as per the docs:

// for security TypeNameHandling is required when deserializing
Stockholder newStockholder = JsonConvert.DeserializeObject<Stockholder>(jsonTypeNameAuto, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
});

It is worth noting that the documentation is deserializing a Concrete class that contains a collection of Abstract classes.

As an experiment try creating a throw-away class (concrete) that has a single property with your list of abstract objects and see if you can serialize and deserialize that.

UPDATE:

I just tested the following code in LINQPad:

void Main()
{
    var test = new List<Business>();
    test.Add(new Hotel { Name = "Hilton", Stars = 5 });
    test.Add(new Pool { Name = "Big Splash", Capacity = 500 });

    test.Dump();

    string json = JsonConvert.SerializeObject(test, Newtonsoft.Json.Formatting.Indented, new JsonSerializerSettings
    {
        TypeNameHandling = TypeNameHandling.All
    });

    json.Dump();

    var businesses = JsonConvert.DeserializeObject<List<Business>>(json, new JsonSerializerSettings
    {
        TypeNameHandling = TypeNameHandling.All
    });

    businesses.Dump();
}

// Define other methods and classes here
public abstract class Business
{
    public string Name { get;set; }
}
public class Hotel : Business
{
    public int Stars { get;set; }
}
public class Pool : Business
{
    public int Capacity { get;set;}
}

It worked perfectly. Abstract collection serialized to:

{
  "$type": "System.Collections.Generic.List`1[[UserQuery+Business, query_jvrdcu]], mscorlib",
  "$values": [
    {
      "$type": "UserQuery+Hotel, query_jvrdcu",
      "Stars": 5,
      "Name": "Hilton"
    },
    {
      "$type": "UserQuery+Pool, query_jvrdcu",
      "Capacity": 500,
      "Name": "Big Splash"
    }
  ]
}

The original and the deserialized collections matched.

Problem

i'm trying to serialize and deserialize a list of `abstract` classes (`mustinherit` for vb), obviusly inside it there are only instances of derived classes. I've decorated the list parameter with the `JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto)` obtaining an output that look like this: But when i deserialize it keep saying that he cannot deserialize an abstract class. http://james.newtonking.com/json/help/index.html?topic=html/SerializeTypeNameHandling.htm ``` public class ConcreteClass { private ObservableCollection<AbstractClass> _Nodes = new ObservableCollection<AbstractClass>(); //<Newtonsoft.Json.JsonProperty(itemtypenamehandling:=Newtonsoft.Json.TypeNameHandling.Auto)> public ObservableCollection<AbstractClass> Nodes { get { return this._Nodes; } } public string Name { get; set; } public int Id { get; set; } } public abstract class AbstractClass { private ObservableCollection<AbstractClass> _Nodes = new ObservableCollection<AbstractClass>(); [Newtonsoft.Json.JsonProperty(itemtypenamehandling = Newtonsoft.Json.TypeNameHandling.Auto)] public ObservableCollection<AbstractClass> Nodes { get { return this._Nodes; } } } ``` removing the commented line it works!

Original source