using System.Collections;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using System.Text.Json.Nodes;
public class MyBaseClass;
public abstract class ValueObject;
public class MyValueObject : ValueObject;
public class NativePolymorphicTypInfoResolver : DefaultJsonTypeInfoResolver {
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options) {
JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options);
Type baseValueObjectType = typeof(ValueObject);
if (jsonTypeInfo.Type == baseValueObjectType) {
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions {
TypeDiscriminatorPropertyName = "$mytype",
IgnoreUnrecognizedTypeDiscriminators = true,
UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization,
.Where(t => t.IsSubclassOf(typeof(ValueObject)));
foreach (var t in types.Select(t => new JsonDerivedType(t, t.Name.ToLowerInvariant())))
jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(t);
public ValueObject? ValueObject { get; set; }
public static void Test()
var rootObject = new RootObject { ValueObject = new MyValueObject() };
var options = new JsonSerializerOptions
TypeInfoResolver = new NativePolymorphicTypInfoResolver(),
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
var json = JsonSerializer.Serialize(rootObject, options);
Assert.That("""{"valueObject":{"$mytype":"myvalueobject"}}""" == json);
public static void Main()
Console.WriteLine("Environment version: {0} ({1}), {2}", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version, Environment.OSVersion);
Console.WriteLine("System.Text.Json version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");