Skip to content

Unseal JsonStringEnumConverter #30486

@josundt

Description

@josundt

Background and Motivation

JsonStringEnumConverter can be configured using a couple of parameters. But since the type is marked sealed, it can be awkward to configure when applied via the JsonConverter attribute, leading to awkward workarounds like this one.

API Proposal

namespace System.Text.Json.Serialization
{
-    public sealed class JsonStringEnumConverter : JsonConverterFactory
+    public class JsonStringEnumConverter : JsonConverterFactory
    {
        public JsonStringEnumConverter() { }
        public JsonStringEnumConverter(JsonNamingPolicy? namingPolicy = null, bool allowIntegerValues = true) { }
-        public override bool CanConvert(Type typeToConvert) { throw null; }
+        public sealed override bool CanConvert(Type typeToConvert) { throw null; }
-        public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { throw null; }
+        public sealed override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { throw null; }
    }
}

Risks

Unsealing public types is generally not considered a breaking change. It might break reflection in the hypothetical scenario where a user depends on the result of typeof(JsonStringEnumConverter).IsSealed.

Original proposal by @josundt (click to view) In our APIs, we serialize most enums as strings (no case conversion) since string enums make APIs more self-explanatory, but for **flag enums** we serialize with the numeric value since strings would prevent bitwise flag enum operations.

With NewtonSoft.Json, we accomplished the described serialization behavior by creating our own converter that inherited from NewtonSoft's StringEnumConverter.

This would have been possible and even easier with System.Text.Json, if only the JsonStringEnumConverter class was not sealed.

If it was not sealed, I could have done this simply by overriding the CanConvert method like below:

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace MyNamespace
{
    public class JsonStringEnumNumericFlagConverter : JsonStringEnumConverter
    {
        public JsonStringEnumNumericFlagConverter()
            : base() {}

        public JsonStringEnumNumericFlagConverter(JsonNamingPolicy namingPolicy = null, bool allowIntegerValues = true)
            : base(namingPolicy, allowIntegerValues) {}

        public override bool CanConvert(Type typeToConvert)
        {
            return typeToConvert.IsEnum
                && typeToConvert.GetCustomAttributes(typeof(FlagsAttribute), false).Length == 0;
        }
    }
}

Can you please make this extensibility point available ("un-sealing" the class)?

Metadata

Metadata

Labels

api-approvedAPI was approved in API review, it can be implementedarea-System.Text.JsonenhancementProduct code improvement that does NOT require public API changes/additions

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions