I'm moving some libraries to .net 8 and I'm trying to use the new JsonNamingPolicy.SnakeCaseLower for enums (I have a custom converter that I currently use that uses reflection but I want to drop it). I can serialize an enum to snake case using this JsonSerializerOptions
JsonSerializerOptions options = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
};
options.Converters.Add(new JsonStringEnumConverter(namingPolicy: JsonNamingPolicy.SnakeCaseLower));
The problem is that according to the documentation The non-generic JsonStringEnumConverter type is not supported for AOT. The solution given is using [JsonSourceGenerationOptions(UseStringEnumConverter = true)]
in the class inheriting from JsonSerializerContext
but then I lose the naming policy for enums.
Is there a way to use JsonNamingPolicy.SnakeCaseLower globally for all enums in an AOT friendly way?
This is not implemented as of .NET 8, see [API Proposal]: Add option to specify JsonNamingPolicy for enum serialization on JsonSourceGenerationOptions #92828.
Recently there has been added
UseStringEnumConverter
flag toJsonSourceGenerationOptions
, but there is no way to configure naming policy for these converters. -ithline.Sounds reasonable. -eiriktsarpalis.
MSFT's Eirik Tsarpalis suggests, as a workaround, to define a JsonStringEnumConverter<TEnum>
subtype for your required naming policy and, for each enum, add it to your serialization context, e.g. like so:
public class SnakeCaseLowerStringEnumConverter<TEnum>()
: JsonStringEnumConverter<TEnum>(JsonNamingPolicy.SnakeCaseLower)
where TEnum : struct, Enum;
[JsonSourceGenerationOptions(
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = JsonKnownNamingPolicy.SnakeCaseLower,
Converters = new[] {
// Add all known enums here
typeof(SnakeCaseLowerStringEnumConverter<FirstEnum>),
typeof(SnakeCaseLowerStringEnumConverter<SecondEnum>),
//...
typeof(SnakeCaseLowerStringEnumConverter<LastEnum>)})]
// Add all known enums here also
[JsonSerializable(typeof(FirstEnum)),
JsonSerializable(typeof(SecondEnum)),
//...
JsonSerializable(typeof(LastEnum))]
// And also add all other root types to be serialized in this context
[JsonSerializable(typeof(MyModel)),]
public partial class SnakeCaseLowerContext : JsonSerializerContext { }
This, however, requires knowing all the enum types in advance. There's no way to set a blanket policy.