88using System . Text . Json ;
99using System . Text . Json . Serialization ;
1010
11- // https://github.com/dotnet/runtime/issues/74385#issuecomment-1705083109.
12- internal sealed class JsonEnumMemberConverter < TEnum > : JsonStringEnumConverter < TEnum > where TEnum : struct , Enum
11+ internal sealed class JsonEnumMemberConverter < TEnum > : JsonConverter < TEnum > where TEnum : struct , Enum
1312{
14- public JsonEnumMemberConverter ( ) : base ( ResolveNamingPolicy ( ) )
15- {
16- }
13+ private readonly Dictionary < string , string > _enumFields = typeof ( TEnum ) . GetFields ( BindingFlags . Public | BindingFlags . Static )
14+ . Select ( field => ( Name : field . Name , Attribute : field . GetCustomAttribute < EnumMemberAttribute > ( ) ) )
15+ . Where ( item => item . Attribute != null && item . Attribute . Value != null )
16+ . ToDictionary ( item => item . Name , item => item . Attribute . Value ) ;
1717
18- private static JsonNamingPolicy ResolveNamingPolicy ( )
18+ public override TEnum Read ( ref Utf8JsonReader reader , Type typeToConvert , JsonSerializerOptions options )
1919 {
20- return new EnumMemberNamingPolicy ( typeof ( TEnum ) . GetFields ( BindingFlags . Public | BindingFlags . Static )
21- . Select ( fieldInfo => new KeyValuePair < string , string > ( fieldInfo . Name , fieldInfo . GetCustomAttribute < EnumMemberAttribute > ( ) ? . Value ) )
22- . Where ( kvp => kvp . Value != null )
23- . ToDictionary ( kvp => kvp . Key , kvp => kvp . Value ) ) ;
20+ var stringValue = reader . GetString ( ) ;
21+
22+ var enumField = _enumFields . SingleOrDefault ( item => item . Value . Equals ( stringValue , StringComparison . Ordinal ) ) ;
23+
24+ if ( enumField . Key == null )
25+ {
26+ throw new JsonException ( $ "Unknown enum value '{ stringValue } ' for enum type '{ typeof ( TEnum ) . Name } '.") ;
27+ }
28+
29+ if ( ! Enum . TryParse ( enumField . Key , out TEnum enumValue ) )
30+ {
31+ throw new JsonException ( $ "Unable to convert '{ stringValue } ' to a valid enum value of type '{ typeof ( TEnum ) . Name } '.") ;
32+ }
33+
34+ return enumValue ;
2435 }
2536
26- private sealed class EnumMemberNamingPolicy : JsonNamingPolicy
37+ public override void Write ( Utf8JsonWriter writer , TEnum value , JsonSerializerOptions options )
2738 {
28- private readonly IReadOnlyDictionary < string , string > _map ;
39+ var enumName = value . ToString ( ) ;
2940
30- public EnumMemberNamingPolicy ( IReadOnlyDictionary < string , string > map ) => _map = map ;
41+ if ( ! _enumFields . TryGetValue ( enumName , out var stringValue ) )
42+ {
43+ throw new JsonException ( $ "Unable to convert '{ enumName } ' to a valid enum value of type '{ nameof ( String ) } '.") ;
44+ }
3145
32- public override string ConvertName ( string name ) => _map . TryGetValue ( name , out var newName ) ? newName : name ;
46+ writer . WriteStringValue ( stringValue ) ;
3347 }
3448}
0 commit comments