Reputation: 361
I'm using Json.Net and trying to serialize and deserialize a List that contains objects of multiple types. I'm struggling to find a way to end up with a List that contains objects of my derived types, instead, I end up with a list of base types.
My code example makes it pretty clear what is happening:
public class Vehicle{
public int wheels = 4;
}
public class Truck : Vehicle {
public int airhorns = 1;
}
static void Main (string[] args) {
List<Vehicle> vehicles = new List<Vehicle> ();
vehicles.Add (new Vehicle ());
vehicles.Add (new Truck ());
foreach (Vehicle v in vehicles) {
Console.WriteLine ("Before deserializing, we have a: " + v.GetType ());
}
string s = JsonConvert.SerializeObject (vehicles);
List<Vehicle> deserialized = JsonConvert.DeserializeObject<List<Vehicle>> (s);
foreach (Vehicle v in deserialized) {
Console.WriteLine ("After deserializing, we have a: " + v.GetType ());
}
}
And the results of running this are:
Before deserializing, we have a: Vehicle
Before deserializing, we have a: Truck
After deserializing, we have a: Vehicle
After deserializing, we have a: Vehicle
I'd like to end up with a Truck in my deserialized list. One thing to note is that the json in string "s" does include the airhorns variable. So that data is present.
I've gone through the JSON docs, and haven't found anything that does exactly what I'm looking for. I looked into hacking CustomCreationConverters ( http://james.newtonking.com/json/help/index.html?topic=html/CustomCreationConverter.htm ) which seem like they could potentially be used to instantiate the correct derived class, but that method doesn't provide any of the json data, so I can't determine the type.
I'm willing to add another field that might explicitly define "Class:Vehicle" or "Class:Truck", though I'm not sure how to use that yet. Maybe after creating the correct class, I could JsonConvert.PopulateObject on the new object... but I'd then need to deal with json fragments.
Any ideas? Thanks!
Upvotes: 4
Views: 2588
Reputation: 15354
Just set TypeNameHandling
and use this setting both in serialization and deserialization.
var settings = new JsonSerializerSettings() {
TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All
};
string s = JsonConvert.SerializeObject(vehicles, settings);
List<Vehicle> deserialized = JsonConvert.DeserializeObject<List<Vehicle>>(s,settings);
foreach (Vehicle v in deserialized)
{
Console.WriteLine("After deserializing, we have a: " + v.GetType());
}
OUTPUT:
Before deserializing, we have a: SO3.Form1+Vehicle
Before deserializing, we have a: SO3.Form1+Truck
After deserializing, we have a: SO3.Form1+Vehicle
After deserializing, we have a: SO3.Form1+Truck
Upvotes: 1