12

I have 3 classes:

class Person {
    public bool IsFemale { get; set; }
}

class Female : Person {
    public string FemaleSpecificProperty { get; set; }
}

class Male: Person { 
    public string MaleSpecificProperty { get; set; }
}

How can I deserialize given JSON string into specific instances (Female or Male) based on the value of Person.IsFemale property? (upfront I dont know which exact type has been used and that property is the only indication)

I looked at employing CustomCreationConverter<T> but couldn't figure out how to make it work here.

jgauffin
  • 99,844
  • 45
  • 235
  • 372
Maxim
  • 962
  • 2
  • 9
  • 21
  • 1
    Take a look at http://stackoverflow.com/questions/8030538/how-to-implement-custom-jsonconverter-in-json-net-to-deserialize-a-list-of-base – alex Jul 06 '13 at 07:18

1 Answers1

14

Here is converter for your person class. It gets IsFemale field value, and based on it creates Female or Male person, which is populated by serializer:

public class PersonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(Person).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType,
        object existingValue, JsonSerializer serializer)
    {
        JObject jObject = JObject.Load(reader);
        var isFemale = (bool)jObject["IsFemale"];
        Person target = isFemale ? (Person)new Female() : new Male();
        serializer.Populate(jObject.CreateReader(), target);
        return target;
    }

    public override void WriteJson(JsonWriter writer, object value, 
        JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Usage:

List<Person> people = new List<Person>
{
    new Male { IsFemale = false, MaleSpecificProperty = "Y" },
    new Male { IsFemale = false, MaleSpecificProperty = "Y" },
    new Female { IsFemale = true, FemaleSpecificProperty = "X" }
};

string json = JsonConvert.SerializeObject(people);
var result = 
     JsonConvert.DeserializeObject<List<Person>>(json, new PersonConverter());

Also take a look on question suggested by alex: How to implement custom JsonConverter

Community
  • 1
  • 1
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • Another gotcha is the Person class seems to require a public default constructor or the converter may try to call the existing constructor with null arguments – pete Feb 01 '22 at 22:05