The context
I have a Web API that returns a list of derived types (all with the same base type) serialized as JSON using Json.NET. Client code then parses that JSON back into a list of derived types. This is done via an API Client that has references to the same class objects used by the Web API. And both the client and server are using Json.NET's TypeNameHandling.Objects feature.
The problem
When a new derived type is added to the Web API, this causes the client-side deserialization to throw an exception due to the client not having a reference to the new derived type's class.
The goal
Instead of throwing an exception, the deserializer should default to a specific "Unknown" derived class when the type is unknown to the client.
The constraint
I don't want to introduce deserialization logic that requires a code change every time a new derived type is added, i.e., a switch
statement on the type. I want to continue to use Json.NET's built-in type handling feature, but with the "default to Unknown" logic.
The code
Here's sample code highlighting the problem:
public abstract class Animal { }
public class Unknown : Animal { }
public class Dog : Animal { }
public class Cat : Animal { }
public class Dummy : Animal { } // to be swapped out of the JSON with a "new" derived type
var animals = new List<Animal>()
{
new Dog(),
new Cat(),
new Dummy()
};
var settings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.Objects,
};
var json = JsonConvert.SerializeObject(animals, settings);
// simulate unknown derived type in JSON
json = json.Replace("Dummy", "NewAnimal");
// throws serialization exception
var deserializedAnimals = JsonConvert.DeserializeObject<List<Animal>>(json, settings);
// goal: deserializedAnimals should contain 3 objects of type { Dog, Cat, Unknown }