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); } }