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