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