using System.Reflection; using System.Runtime.Serialization; using System.Text.Json; using System.Text.Json.Serialization; namespace Bit.Core.Utilities; /// /// A custom JSON converter for enum types that respects the when serializing and deserializing. /// /// The enum type to convert. Must be a struct and implement Enum. /// /// This converter builds lookup dictionaries at initialization to efficiently map between enum values and their /// string representations. If an enum value has an , the attribute's Value /// property is used as the JSON string; otherwise, the enum's ToString() value is used. /// public class EnumMemberJsonConverter : JsonConverter where T : struct, Enum { private readonly Dictionary _enumToString = new(); private readonly Dictionary _stringToEnum = new(); public EnumMemberJsonConverter() { var type = typeof(T); var values = Enum.GetValues(); foreach (var value in values) { var fieldInfo = type.GetField(value.ToString()); var attribute = fieldInfo?.GetCustomAttribute(); var stringValue = attribute?.Value ?? value.ToString(); _enumToString[value] = stringValue; _stringToEnum[stringValue] = value; } } public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var stringValue = reader.GetString(); if (!string.IsNullOrEmpty(stringValue) && _stringToEnum.TryGetValue(stringValue, out var enumValue)) { return enumValue; } throw new JsonException($"Unable to convert '{stringValue}' to {typeof(T).Name}"); } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) => writer.WriteStringValue(_enumToString[value]); }