user246392
user246392

Reputation: 3027

How to enable JsonStringEnumConverter for all enums in .NET AOT

It looks like JsonStringEnumConverter requires dynamic code and we should switch to JsonStringEnumConverter<T> in AOT.

[JsonConverter(typeof(JsonStringEnumConverter<MyEnum>))]
public enum MyEnum { Foo, Bar }

[JsonSerializable(typeof(MyEnum))]
public partial class MyJsonSerializerContext : JsonSerializerContext { }

I have many enums. Is it possible to create a global policy so that each enum is converted into its string representation and we avoid attributes?

Upvotes: 3

Views: 2061

Answers (1)

dbc
dbc

Reputation: 117105

As stated in How to use source generation in System.Text.Json: Blanket policy, you can apply [JsonSourceGenerationOptions(UseStringEnumConverter = true)] to your serialization contexts to force all enums to be serialized as strings:

Instead of using the JsonStringEnumConverter<TEnum> type, you can apply a blanket policy to serialize enums as strings by using the JsonSourceGenerationOptionsAttribute. Create a JsonSerializerContext class and annotate it with the JsonSerializableAttribute and JsonSourceGenerationOptionsAttribute attributes

Thus you should modify your MyJsonSerializerContext as follows:

[JsonSourceGenerationOptions(UseStringEnumConverter = true)]
[JsonSerializable(typeof(MyEnum))]
public partial class MyJsonSerializerContext : JsonSerializerContext { }

The code shown in the question does not use a naming policy such as JsonNamingPolicy.CamelCase for enum serialization. If you need one, note that, as indicated in issue #92828, as of .NET 8 there does not seem to be a way to configure one with this approach. I.e. the setting UseStringEnumConverter = true lacks feature parity with new JsonStringEnumConverter(JsonNamingPolicy.CamelCase). The workaround suggested by MSFT's Eirik Tsarpalis is to apply the required converters to the serialization context instead of to each enum:

public class CamelCaseEnumConverter<TEnum>() : 
    JsonStringEnumConverter<TEnum>(JsonNamingPolicy.CamelCase) where TEnum : struct, Enum;

[JsonSourceGenerationOptions(
    Converters = new[] { 
        // Add all known enums here
        typeof(CamelCaseEnumConverter<MyEnum>)}),
// Add all known enums here also (which you were already doing):
 JsonSerializable(typeof(MyEnum))]
public partial class MyJsonSerializerContext : JsonSerializerContext { }

For more see: Use a Blanket policy to serialize enums as strings with snake case.

Upvotes: 1

Related Questions