Files
prefab-page-detail/Prefab.Base/PrefabEnumJsonConverters.cs
2025-10-27 17:39:18 -04:00

66 lines
2.1 KiB
C#

using System.Text.Json;
using System.Text.Json.Serialization;
namespace Prefab.Base;
/// <summary>
/// Creates JSON converters that serialize Prefab enums using their logical names.
/// </summary>
public sealed class PrefabEnumJsonConverterFactory : JsonConverterFactory
{
/// <inheritdoc />
public override bool CanConvert(Type typeToConvert)
{
if (!typeToConvert.IsClass)
{
return false;
}
var baseType = typeToConvert;
while (baseType is not null)
{
if (baseType.IsGenericType && baseType.GetGenericTypeDefinition() == typeof(PrefabEnum<>))
{
return true;
}
baseType = baseType.BaseType;
}
return false;
}
/// <inheritdoc />
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
var converterType = typeof(PrefabEnumJsonConverter<>).MakeGenericType(typeToConvert);
return (JsonConverter)Activator.CreateInstance(converterType)!;
}
/// <summary>
/// Converter used for concrete Prefab enum types.
/// </summary>
private sealed class PrefabEnumJsonConverter<TEnum> : JsonConverter<TEnum> where TEnum : PrefabEnum<TEnum>
{
/// <inheritdoc />
public override TEnum? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
var name = reader.GetString() ?? string.Empty;
return PrefabEnum<TEnum>.FromName(name);
}
if (reader.TokenType == JsonTokenType.Number && reader.TryGetInt32(out var value))
{
return PrefabEnum<TEnum>.FromValue(value);
}
throw new JsonException($"Unexpected token {reader.TokenType} when parsing {typeof(TEnum).Name}.");
}
/// <inheritdoc />
public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options) => writer.WriteStringValue(value.Name);
}
}