Skip to content

Instantly share code, notes, and snippets.

@davepermen
Created March 7, 2025 23:39
Show Gist options
  • Save davepermen/a9006eef32306404db8e5e37a509991e to your computer and use it in GitHub Desktop.
Save davepermen/a9006eef32306404db8e5e37a509991e to your computer and use it in GitHub Desktop.
using System;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
/* demo */
var options = JsonSerializerOptions.Web.WithPolymorphictypeInfoFor<Event>();
Event[] events = [new WebButtonEvent("123"), new HomeStateEvent("home/kitchen", "on")];
var serialized = JsonSerializer.Serialize(events, options);
Console.WriteLine(serialized);
var _events = JsonSerializer.Deserialize<Event[]>(serialized, options);
foreach (var _event in _events)
{
Console.WriteLine(_event switch
{
WebButtonEvent button => $"webbuttonevent: {button.Id}",
HomeStateEvent home => $"homestateevent: {home.Path} = {home.Value}",
_ => "error"
});
}
/* demo types */
record Event;
record WebButtonEvent(string Id) : Event;
record HomeStateEvent(string Path, string Value) : Event;
/* helper extensions */
public static class JsonExtensions
{
public static JsonSerializerOptions WithPolymorphictypeInfoFor<T>(this JsonSerializerOptions options) => new(options)
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver().WithAddedModifier(JsonExtensions.AddNativePolymorphicTypeInfoFor<Event>)
};
static void AddNativePolymorphicTypeInfoFor<T>(JsonTypeInfo jsonTypeInfo)
{
Type baseValueObjectType = typeof(T);
if (jsonTypeInfo.Type == baseValueObjectType)
{
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions
{
TypeDiscriminatorPropertyName = "type",
IgnoreUnrecognizedTypeDiscriminators = true,
UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization,
};
var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where(t => t.IsSubclassOf(baseValueObjectType)); // Fixed MyBaseClass => ValueObject
foreach (var t in types.Select(t => new JsonDerivedType(t, t.Name.ToLowerInvariant())))
{
jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(t);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment