0

Since I had to search forever for an answer, that would just work as is, I will provide an example here, when you serialize and deserialize an object with a composite pattern structure.

My problem was deserializing this kind of class structure (https://en.wikipedia.org/wiki/Composite_pattern):

abstract class BaseClass
{    
    public int Id { get; set; }
}

class Leaf : BaseClass
{
    public string Foo { get; set; }
}

class Composite : BaseClass
{
    public List<BaseClass> ClassList = new List<BaseClass>();
}

Serialization worked by using:

var composite = new Composite();
JsonConvert.SerializeObject(composite, Formatting.Indented);

Deserialziation didn't work out of box.

Dodo
  • 137
  • 5

1 Answers1

-1

Solution for deserialization is to build a CustomConverter:

public class BaseClassJsonConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(BaseClass) == objectType;
        }

        public override object ReadJson(JsonReader reader, Type objectType,
            object existingValue, JsonSerializer serializer)
        {
            try
            {
                var jObject = JObject.Load(reader);

                var jsonSerializerSettings = new JsonSerializerSettings();
                jsonSerializerSettings.Converters.Add(new BaseClassJsonConverter());

                if (jObject.ContainsKey("Foo"))
                    return JsonConvert.DeserializeObject<Leaf>(jObject.ToString(), jsonSerializerSettings);
                else if (jObject.ContainsKey("ClassList"))
                    return JsonConvert.DeserializeObject<Composite>(jObject.ToString(), jsonSerializerSettings);
                else
                    throw new System.SystemException("Class not implemented");
                return null;
            }
            catch (JsonReaderException)
            {
                return null;
            }
        }
        public override bool CanWrite
        {
            get { return false; }
        }

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

Key difference to other answers I found is that they were missing to put the settings in the ReadJson into the SeserialzieObject again, that way it couldn't handle the deserialization of a recursive structure (Deserializing JSON to abstract class).

Now you either decorate your BaseClass with: [JsonConverter(typeof(BaseConverter))]

Or you call the deserialization with the converter in the settings:

var jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.Converters.Add(new BaseClassJsonConverter());
JsonConvert.DeserializeObject<BaseClass>(jsonString, jsonSerializerSettings);
Dodo
  • 137
  • 5