I have a multi-level polymorphic type hierarchy that I previously serialized using the data contract serializers. I would like to convert that to System.Text.Json using the new type hierarchy support in .NET 7. Where should I apply the [JsonDerivedType]
attributes so that "grandchild" and other deeply derived subtypes of subtypes can be serialized correctly?
My original type hierarchy looked like this:
[KnownType(typeof(DerivedType))]
public abstract class BaseType { } // Properties omitted
[KnownType(typeof(DerivedOfDerivedType))]
public class DerivedType : BaseType { public string DerivedValue { get; set; } }
public class DerivedOfDerivedType : DerivedType { public string DerivedOfDerivedValue { get; set; } }
I replaced the [KnownType]
attributes with [JsonDerivedType]
attributes as follows:
[JsonDerivedType(typeof(DerivedType), "DerivedType:#MyNamespace")]
public abstract class BaseType { } // Properties omitted
[JsonDerivedType(typeof(DerivedOfDerivedType), "DerivedOfDerivedType:#MyNamespace")]
public class DerivedType : BaseType { public string DerivedValue { get; set; } }
public class DerivedOfDerivedType : DerivedType { public string DerivedOfDerivedValue { get; set; } }
However when I serialize as List<BaseType>
as follows:
var list = new List<BaseType> { new DerivedOfDerivedType { DerivedValue = "value 1", DerivedOfDerivedValue = "value of DerivedOfDerived" } };
var json = JsonSerializer.Serialize(list);
I get the following exception:
System.NotSupportedException: Runtime type 'MyNamespace.DerivedOfDerivedType' is not supported by polymorphic type 'MyNamespace.BaseType'. Path: $.
---> System.NotSupportedException: Runtime type 'MyNamespace.DerivedOfDerivedType' is not supported by polymorphic type 'MyNamespace.BaseType'.
Where should the JsonDerivedType
attributes be applied to make this work?
t.DerivedType.GetCustomAttribute<JsonDerivedTypeAttribute>()
withAttribute.IsDefined()
. If multiple attributes are applied, the former will throw. 2) Addderived
to the hash set in case somebody manually added a derived type to multiple base types. See dotnetfiddle.net/l0hFBS. – Vincenty