Skip to content
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

EnumMember is not applied when enum value is a combination of flags. #1016

Open
filzrev opened this issue Dec 3, 2024 · 2 comments
Open

Comments

@filzrev
Copy link
Contributor

filzrev commented Dec 3, 2024

Describe the bug
When serialize enum value combinations.
value is serialized by default enum name.
And the name that is specified by EnumMember is not used.

To Reproduce

Test Code

[Flags]
public enum TestEnum
{
	[JsonStringEnumMemberName("A")]
	[EnumMember(Value = "A")]
	AAA = 1,
	[JsonStringEnumMemberName("B")]
	[EnumMember(Value = "B")]
	BBB = 2,
}

[Fact]
void YamlDotNetTest()
{
	var serializer = new SerializerBuilder().Build();

	// Arrange
	var value = TestEnum.AAA | TestEnum.BBB;

	// Act
	var result = serializer.Serialize(value);

	// Assert
	result.Should().Be("A, B\r\n"); // Failed. Expected: "A,B\r\n" but Actual: "AAA, BBB\r\n"
}

Serialize result of System.Text.Json / NewtonsoftJson

When serialize same value with System.Text.Json / NewtonsoftJson enum value is serialized as expected.

// System.Text.Json use `JsonStringEnumMemberName` attribute (EnumMember attribute is not used)
[Fact]
void SystemTextJsonTest()
{	
	var options = new JsonSerializerOptions { };
	options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
	
	// Arrange
	var value = TestEnum.AAA | TestEnum.BBB;

	// Act
	var result = System.Text.Json.JsonSerializer.Serialize(value, options);

	// Assert
	result.Should().Be("\"A, B\""); // Success
}

// NewtonsoftJson use `EnumMember` attribute.
[Fact]
void NewtonsoftJsonTest()
{
	// Arrange
	var value = TestEnum.AAA | TestEnum.BBB;

	// Act
	var result = JsonConvert.SerializeObject(value, new Newtonsoft.Json.Converters.StringEnumConverter());

	// Assert
	result.Should().Be("\"A, B\""); // Success
}
@EdwardCooke
Copy link
Collaborator

We do support enum member but only in .net core. Full framework doesn’t have that functionality. Are you doing this in a .net core 6/7/8 app or full framework 4.x?

@filzrev
Copy link
Contributor Author

filzrev commented Dec 4, 2024

I'm using .NET 8 or later.
So there is no need for .NET Framework supports on my usecase.

By the way, is there any reasons that exclude EnumMember support for .NET Framework 4.x?

It's explicitly excluded by #ifdef preprocessors.
But these code seems it can successfully build when targeting .NET Framework 4.7 or later. (It support .NET Standard 2.0)

public override string GetEnumName(Type enumType, string name)
{
#if NETSTANDARD2_0_OR_GREATER || NET6_0_OR_GREATER
foreach (var enumMember in enumType.GetMembers())
{
var attribute = enumMember.GetCustomAttribute<EnumMemberAttribute>();
if (attribute?.Value == name)
{
return enumMember.Name;
}
}
#endif
return name;
}
public override string GetEnumValue(object enumValue)
{
if (enumValue == null)
{
return string.Empty;
}
var result = enumValue.ToString();
#if NETSTANDARD2_0_OR_GREATER || NET6_0_OR_GREATER
var type = enumValue.GetType();
var enumMembers = type.GetMember(result);
if (enumMembers.Length > 0)
{
var attribute = enumMembers[0].GetCustomAttribute<EnumMemberAttribute>();
if (attribute?.Value != null)
{
result = attribute.Value;
}
}
#endif
return result!;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants