简体   繁体   中英

Deserializing lists of mixed types using Json.net

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!

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   

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM