Custom enum value name in System.Text.Json
When serializing enums to JSON, it's usually better to serialize them as descriptive strings than incomprehensible magic numbers. Most of the time, it's good enough to simply use the names of enum members for this purpose. However, these must follow the rules for identifier names in C#, so they might be too restrictive if you need to use specific string values because of interoperability with other systems.
Newtonsoft Json.NET serializer allows you to use the EnumMember
attribute in such cases:
[JsonConverter(typeof(StringEnumConverter))]
public enum SampleEnum
{
ValueOne = 1,
[EnumMember(Value = "Value Two")]
ValueTwo = 2,
}
When this attribute is present on an enum member, its value will be used for serialization instead of the enum member name.
[Test]
public void NewtonsoftJsonReadsEnumMemberAttribute()
{
var original = new SampleObject
{
Value = SampleEnum.ValueTwo,
};
var json = JsonConvert.SerializeObject(original);
json.Should().Be("""{"Value":"Value Two"}""");
}
Unfortunately, the EnumMember
attribute is ignored when using the new System.Text.Json
serializer:
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum SampleEnum
{
ValueOne = 1,
[EnumMember(Value = "Value Two")]
ValueTwo = 2,
}
[Test]
public void SystemTextJsonDoesNotReadEnumMemberAttribute()
{
var original = new SampleObject
{
Value = SampleEnum.ValueTwo,
};
var json = JsonSerializer.Serialize(original);
json.Should().Be("""{"Value":"ValueTwo"}""");
}
There's a GitHub issue with a long discussion about this missing feature which makes it clear that no built-in support is planned for it any time soon, if ever. However, I don't think that's much of an issue. The serializer is easily extendable, so you can write your own custom converter for this purpose. You can even find a working example with EnumMember
attribute support in the same Github issue.
Or even better, use JsonStringEnumMemberConverter from the Macross.Json.Extensions NuGet package instead:
[JsonConverter(typeof(JsonStringEnumMemberConverter))]
public enum SampleEnum
{
ValueOne = 1,
[EnumMember(Value = "Value Two")]
ValueTwo = 2,
}
[Test]
public void SystemTextJsonCustomConverterReadsEnumMemberAttribute()
{
var original = new SampleObject
{
Value = SampleEnum.ValueTwo,
};
var json = JsonSerializer.Serialize(original);
json.Should().Be("""{"Value":"Value Two"}""");
}
You can find a sample project with working JSON serialization using values from the EnumMember
attribute in my GitHub repository. Feel free to try it out and play with it before implementing a similar solution in your own project.
There are quite a few Newtonsoft Json.NET features that are missing in System.Text.Json
. Fortunately, most of these features can be added by using its extensibility model. Some of them are already implemented for you in the Macross.Json.Extensions NuGet package.