Runtime: Support for EnumMemberAttribute in JsonConverterEnum

Created on 6 Oct 2019  路  6Comments  路  Source: dotnet/runtime

Hi, I wonder if supporting EnumMemberAttribute in JsonConverterEnum is planned and if so what the ETA is?

Json.NET supports EnumMemberAttribute to customize enum name values. It is a well used feature.

You don't need it in 3.0, but you will get a lot of requests for customizing enum names. Design for adding it in the future.

_Originally posted by @JamesNK in https://github.com/dotnet/corefx/pull/38702#issuecomment-503777812_

area-System.Text.Json enhancement

Most helpful comment

For anyone blocked by this, here's a NuGet package with a converter (JsonStringEnumMemberConverter) we can use ahead of the 5.0 drop: Macross.Json.Extensions

Supports nullable enum types and adds EnumMemberAttribute support.

All 6 comments

/cc @steveharter

We should discuss if we want to support this and other attributes from System.Runtime.Serialization before adding them.

The basic scenario here is to provide control of the value names used for enum serialization. DCS and Json.NET use EnumMemberAttribute, XML uses XmlEnumAttribute.

For anyone blocked by this, here's a NuGet package with a converter (JsonStringEnumMemberConverter) we can use ahead of the 5.0 drop: Macross.Json.Extensions

Supports nullable enum types and adds EnumMemberAttribute support.

From @AraHaan in https://github.com/dotnet/runtime/issues/36931:

I personally think that EnumMember should be supported, many users try to use it with the JsonStringEnumConverter that comes shipped with System.Text.Json itself. Because of this they can run into an System.Text.Json.JsonException from doing such which sucks.

Take a look at the draft pr that is on hold because this is 1 of the issues they face when trying to eradicate newtonsoft.json: RehanSaeed/Schema.NET#100

Also take a look at a version of my code which did that, then I have to now struggle trying to get my stuff to compile because now I got to create a string extension method that could allow null strings somehow and then filter it to the enum values accordingly manually which also sucks.
https://paste.mod.gg/giwezarimo.cs
https://paste.mod.gg/nuqofuwamu.cs
https://paste.mod.gg/gunoqemufu.cs

You can literally use this code as a minimal example and as you can tell my code will not compile as this stuff is lacking. Note: I only made this change because of that pull request above I seen that it used EnumMember and that it used a converter I did not really know about so I thought "Wait a second so my manual converters is not needed at all?"

Here is the new pull request for this issue: #37113.

Here is the proposed API to fix this issue. EnumMemberAttribute was considered, but the serializer prefers custom/dedicated attributes. This proposed API takes this into account and proposes a new attribute for this purpose.

Note: Pinging @layomia as this person expressed interested in this proposal.

Rationale and Usage

This may be a nice-to-have; however, as @mikaelkolkinn states, it is a blocker for migrating off of the Newtonsoft Json serializer/deserializer for some customers.

Proposed API

The proposed attribute would be the following. It would permit the overriding of any JsonNamingPolicy provided in the serializer.

namespace System.Text.Json.Serialization
{
    /// <summary>
    /// Specifies the enum member that is present in the JSON when serializing and deserializing.
    /// This overrides any naming policy specified by <see cref="JsonNamingPolicy"/>.
    /// </summary>
    [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
    public sealed class JsonStringEnumMemberAttribute : JsonAttribute
    {
        /// <summary>
        /// Initializes a new instance of <see cref="JsonStringEnumMemberAttribute"/> with the specified enum member name.
        /// </summary>
        /// <param name="name">The name of the enum member.</param>
        public JsonStringEnumMemberAttribute(string name)
        {
            Name = name;
        }

        /// <summary>
        /// The name of the enum member.
        /// </summary>
        public string Name { get; }
    }
}

The usage of this attribute would be the following.

[JsonConverter(typeof(JsonStringEnumConverter))]
public enum MyCustomJsonStringEnumMemberEnum
{
            [System.Text.Json.Serialization.JsonStringEnumMemberAttribute("one_")]
            One,
            [System.Text.Json.Serialization.JsonStringEnumMemberAttribute("two_")]
            Two,
            [System.Text.Json.Serialization.JsonStringEnumMemberAttribute(null)]
            Null
}

The result of each one of these example enum members when serialized will be the following json values: "one_", "two_", null

Details

The serializer will respect this new attribute on both serialization and deserialization. The serializer will allow any string or null as permissible values in the attribute and will convert it from/to the specified enum member where the attribute is attached to.

This attribute will also override any JsonNamingPolicy provided in the serializer.

Note: this API proposal is not a replacement for #31619, but a compliment to it.

Open Questions

  • Will the API check for any conflicts in enum field naming? Or leave the result as of such state undefined?
  • Should we use JsonPropertyNameAttribute instead of the proposed new attribute?

    • I would recommend not to because the name JsonPropertyNameAttribute does not imply that it could be used on an enum.

    • I am not opposed to this approach, however.

  • Should we actually support the attributes in the System.Runtime.Serialization namespace?

    • I believe that this is a wider discussion than this narrow use case and should require a separate issue to discuss it as it would break the current affinity towards the serializer's own attributes.

  • Could we do without this proposal if #31619 is implemented?

    • Yes, however, I believe there are some business cases where the name would need to be overridden even with a JsonNamingPolicy

Pull Request

See pull request #37113 for an example implementation.

Updates

Was this page helpful?
0 / 5 - 0 ratings