using System.Collections.Generic;
using System.Text.Json.Serialization;
public class GeneralEnumJsonConverter<T> : JsonConverter<T> where T : Enum
private readonly EnumStringLookup<T> enumStringLookup = new();
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
var input = reader.GetString();
return enumStringLookup.Lookup(input);
throw new InvalidCastException($"Invalid value \"{input}\" for {typeof(T)}");
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
writer.WriteStringValue(enumStringLookup.Lookup(value));
public class EnumStringLookup<T> where T : Enum
private readonly Dictionary<string, T> stringToEnumDictionary = new();
private readonly Dictionary<string, T> stringToEnumDictionary2 = new();
private readonly Dictionary<T, string> enumToStringDictionary = new();
internal EnumStringLookup()
foreach (T enumValue in Enum.GetValues(typeof(T)))
var screamValue = PascalToScreamCaseTranslator.TranslateToScreamCase(enumValue.ToString());
stringToEnumDictionary.Add(screamValue, enumValue);
stringToEnumDictionary2.Add(enumValue.ToString(), enumValue);
enumToStringDictionary.Add(enumValue, screamValue);
internal T Lookup(string value)
if (stringToEnumDictionary.ContainsKey(value))
return stringToEnumDictionary[value];
if (stringToEnumDictionary2.ContainsKey(value))
return stringToEnumDictionary2[value];
throw new InvalidCastException($"Invalid value \"{value}\" for {typeof(T)}");
internal string Lookup(T value)
return enumToStringDictionary[value];
public static class PascalToScreamCaseTranslator
public static string TranslateToScreamCase(string pascalCase)
string pascalCase2 = pascalCase;
return string.Concat(pascalCase2.Select((char c, int i) => (i > 0 && ((char.IsUpper(c) && (!char.IsUpper(pascalCase2[i - 1]) || (i < pascalCase2.Length - 1 && !char.IsUpper(pascalCase2[i + 1])))) || (char.IsDigit(c) && !char.IsDigit(pascalCase2[i - 1])))) ? $"_{c}" : c.ToString())).ToUpper();
[JsonConverter(typeof(GeneralEnumJsonConverter<State>))]
public string BillId { get; set; }
public State State { get; set; }
public string BillId { get; set; }
public State State { get; set; }
public static void Main()
State = State.SentToPaymentLane
State = State.SentToPaymentLane
var serialized = JsonSerializer.Serialize(bill);
Console.WriteLine(serialized);
var de = JsonSerializer.Deserialize<Bill>(serialized);
Console.WriteLine($"{de.BillId} - {Enum.GetName(de.State)}");
var serialized2 = JsonSerializer.Serialize(bill, new JsonSerializerOptions { Converters = { new JsonStringEnumConverter() }});
Console.WriteLine(serialized2);
var de2 = JsonSerializer.Deserialize<Bill>(serialized2);
Console.WriteLine($"{de2.BillId} - {Enum.GetName(de2.State)}");
var serialized3 = JsonSerializer.Serialize(billS);
Console.WriteLine(serialized3);
var de3 = JsonSerializer.Deserialize<Bill>(serialized3);
Console.WriteLine($"{de3.BillId} - {Enum.GetName(de3.State)}");