A custom System.Text.Json converter for TimelineEventData that reads JSON documents and deserializes polymorphic event data based on a "type" field or an outer type parameter. It maps known type strings to concrete event data types and returns UnknownEventData for unrecognized types. It also writes values using JsonSerializer.
#nullable enable annotations
namespace LichessNET.Entities.Social.Timeline;
internal class TimelineEventDataConverter : JsonConverter<TimelineEventData>
{
public override TimelineEventData Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using var document = JsonDocument.ParseValue(ref reader);
return DeserializeData(null, document.RootElement, options);
}
public override void Write(Utf8JsonWriter writer, TimelineEventData value, JsonSerializerOptions options)
{
JsonSerializer.Serialize(writer, (object)value, options);
}
internal static TimelineEventData DeserializeData(string type, JsonElement data, JsonSerializerOptions options)
{
if (string.IsNullOrWhiteSpace(type) && data.TryGetProperty("type", out var embeddedType))
type = embeddedType.GetString();
if (data.TryGetProperty("data", out var nestedData))
data = nestedData;
TimelineEventData result = type switch
{
"follow" => data.Deserialize<FollowEventData>(options),
"team-join" => data.Deserialize<TeamJoinEventData>(options),
"team-create" => data.Deserialize<TeamCreateEventData>(options),
"forum-post" => data.Deserialize<ForumPostEventData>(options),
"ublog-post" => data.Deserialize<UblogPostEventData>(options),
"tour-join" => data.Deserialize<TourJoinEventData>(options),
"game-end" => data.Deserialize<GameEndEventData>(options),
"simul-create" => data.Deserialize<SimulCreateEventData>(options),
"simul-join" => data.Deserialize<SimulJoinEventData>(options),
"study-like" => data.Deserialize<StudyLikeEventData>(options),
"plan-start" => data.Deserialize<PlanStartEventData>(options),
"plan-renew" => data.Deserialize<PlanRenewEventData>(options),
"blog-post" => data.Deserialize<BlogPostEventData>(options),
"ublog-post-like" => data.Deserialize<UblogPostLikeEventData>(options),
"stream-start" => data.Deserialize<StreamStartEventData>(options),
_ => null
};
return result ?? new UnknownEventData();
}
}