In .NET 7, we can use JsonDerivedType
to enable polymorphic serialization for a type:
[JsonDerivedType(typeof(ChildClass))]
public class BaseClass
{
public string FirstName { get; set; }
}
public class ChildClass : BaseClass
{
public string LastName { get; set; }
}
Suppose I want every class that derives from BaseClass
to be polymorphically serializable. Is there a succinct way of doing this instead of having to type an annotation per class? Suppose I have dozens of derived types.
You can configure polymorphism with the contract model.
From the documentation
For use cases where attribute annotations are impractical or impossible
In summary, you define a custom IJsonTypeInfoResolver
and apply some reflection to define the polymorphism rules.
Below example shows 2 hard coded types, but you can take it a step further by discovering the derived types via reflection (as long as you can also get the matching discriminator).
public class CustomJsonTypeInfoResolver : DefaultJsonTypeInfoResolver
{
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
{
JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options);
Type baseType = typeof(YourBaseClass);
if (jsonTypeInfo.Type == baseType)
{
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions
{
TypeDiscriminatorPropertyName = "$type" // Or any other of your choosing.
// Other code removed for brevity.
DerivedTypes =
{
new JsonDerivedType(typeof(DerivedType1), "discriminator1"),
new JsonDerivedType(typeof(DerivedType2), "discriminator2")
}
// Or use reflection to retrieve the derived types.
};
}
return jsonTypeInfo;
}
You need to set the TypeInfoResolver on the JsonSerializerOptions
.
Below code shows how to do so for an ASP.NET Core web application.
builder.Services
.AddControllers()
.AddJsonOptions(options => options.JsonSerializerOptions.TypeInfoResolver = new CustomJsonTypeInfoResolver());