-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Framework guidelines dictate that Enum names should be Pascal cased #224
Comments
The only solution I can come up with is to create a convertor: public class JsonStringEnumConverter<TEnum> : JsonConverter<TEnum> where TEnum : struct, Enum
{
public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (typeToConvert == typeof(MyEnum))
{
var type = reader.TokenType;
if (type == JsonTokenType.String)
{
var stringValue = reader.GetString();
switch (stringValue)
{
case "explicit":
return (TEnum)(object)MyEnum.Explicit;
case "all":
return (TEnum)(object)MyEnum.All;
case "none":
return (TEnum)(object)MyEnum.None;
}
}
return default;
}
throw new InvalidOperationException();
}
public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options)
{
if (value is MyEnum myEnum)
{
switch (myEnum)
{
case MyEnum.None:
writer.WriteStringValue("none");
break;
case MyEnum.All:
writer.WriteStringValue("all");
break;
case MyEnum.Explicit:
writer.WriteStringValue("explicit");
break;
}
}
else
{
throw new InvalidOperationException();
}
}
} |
@mtmk -- net8.0 natively has |
yes but it seems to be ignoring the case options for me 😢 |
Okay, I definitely had it working in net6 -- let me get a spike going locally (console net6 app) to validate the settings and I'll get back to you here. |
Alright, got it. This is targeting net6.0 but I'm referencing the 8.0.0 sys.text.json (as you probably are too) // See https://aka.ms/new-console-template for more information
using System.Text.Json;
using System.Text.Json.Serialization;
// object to serialize
var shape = new Shape { Color = Color.Red };
// override the default enum naming policy by passing our own string enum converter instance
var context = new ShapeSerializationContext(new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) }
});
// we pass our custom context instead of ShapeSerializationContext.Default
var json = JsonSerializer.Serialize(shape, context.Shape);
Console.WriteLine(json);
public enum Color
{
Red,
Green,
Blue
}
public class Shape
{
public Color Color { get; set; }
}
[JsonSerializable(typeof(Shape))]
[JsonSerializable(typeof(Color))]
[JsonSourceGenerationOptions(UseStringEnumConverter = true)] // i.e. "red" not 0
public partial class ShapeSerializationContext : JsonSerializerContext
{
} outputs: |
Figuring this out the first time took me hours. |
Here's the variant for net8.0 that will permit AOT publish: // See https://aka.ms/new-console-template for more information
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
// object to serialize
var shape = new Shape { Color = Color.Red };
// override the default enum naming policy by passing our own string enum converter instance
var context = new ShapeSerializationContext(new JsonSerializerOptions
{
// ensures "Color" property will be camel-cased
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
// use new generic version of JsonStringEnumConverter to permit AOT
// need to also pass in the naming policy to ensure the enum values are camel-cased
Converters = { new JsonStringEnumConverter<Color>(JsonNamingPolicy.CamelCase) }
});
Debug.Assert(JsonSerializer.IsReflectionEnabledByDefault == false);
// we pass our custom context instead of ShapeSerializationContext.Default
var json = JsonSerializer.Serialize(shape, context.Shape);
Console.WriteLine(json);
public enum Color
{
Red,
Green,
Blue
}
public class Shape
{
public Color Color { get; set; }
}
[JsonSerializable(typeof(Shape))]
[JsonSerializable(typeof(Color))]
[JsonSourceGenerationOptions(
UseStringEnumConverter = true)] // i.e. "red" not 0
public partial class ShapeSerializationContext : JsonSerializerContext
{
} My csproj: <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
<PublishAot>true</PublishAot>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" Version="8.0.0" />
</ItemGroup>
</Project> |
this is great. worked for me in my little test app. I think I can apply it now. thank you @oising! |
And thank you for your great work giving us a top class dotnet client! |
Framework guidelines dictate that Enum names should be Pascal cased -- then you could avoid the ugly at escape on explicit.
Originally posted by @oising in #212 (comment)
The text was updated successfully, but these errors were encountered: