OpenAPITools / OpenAPITools/openapi-generator

[REQ][C#] Support Case-Insensitive String Enums

Open
#20,297 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Enhancement: Feature
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Is your feature request related to a problem? Please describe.

The Java client offers a useCaseInsensitiveEnums flag in the configuration to support case-insensitive string enums. It would be great if the C# SDK offered the same - it looks like this is requested for other generators in ##16634 and #17398

Describe the solution you'd like

A config option for allowing case-insensitive string enums. Our API sends a webhook that we have defined as an enum in our OpenAPI spec with the values in and out. When attempting to serialize to a model generated via the project - I get this error

Microsoft.AspNetCore.Http.BadHttpRequestException: Failed to read parameter "List<MessageDeliveredCallback> callbackData" from the request body as JSON.
 ---> System.Text.Json.JsonException: The JSON value could not be converted to Bandwidth.Standard.Model.MessageDeliveredCallbackMessage. Path: $[0].message.direction | LineNumber: 22 | BytePositionInLine: 23.
   at System.Text.Json.ThrowHelper.ThrowJsonException(String message)
   at System.Text.Json.Serialization.Converters.EnumConverter`1.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
   at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
   at System.Text.Json.Serialization.JsonConverter`1.TryReadAsObject(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, Object& value)
   .....

This is the generated model definition

   [JsonConverter(typeof(StringEnumConverter))]
    public enum MessageDirectionEnum
    {
        /// <summary>
        /// Enum In for value: in
        /// </summary>
        [EnumMember(Value = "in")]
        In = 1,

        /// <summary>
        /// Enum Out for value: out
        /// </summary>
        [EnumMember(Value = "out")]
        Out = 2
    }

From what I can tell - dotnet doesnt have any built in support for this so we would need a custom CaseInsensitiveEnumConverter<T> class that looks something like

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

public class CaseInsensitiveEnumConverter<T> : JsonConverter<T> where T : struct, Enum
{
    public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var value = reader.GetString();
        if (Enum.TryParse(value, ignoreCase: true, out T result))
        {
            return result;
        }
        throw new JsonException($"Invalid value '{value}' for enum {typeof(T).Name}");
    }

    public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString());
    }
}

to be used on the generated enum classes

using System.Text.Json.Serialization;

[JsonConverter(typeof(CaseInsensitiveEnumConverter<MessageDirectionEnum>))]
public enum MessageDirectionEnum

Looking through the codebase for the csharp generator, there is a lot of custom logic around the enums already with the zeroBasedEnums config option, so ideally we wouldn't want to break that

Describe alternatives you've considered

Clients can set an option to use caseInsensitive serialization - but it would be nice to have this built in

new JsonSerializerOptions
        {
            Converters = { new JsonStringEnumConverter() },
            PropertyNameCaseInsensitive = true
        });

With some guidance on how the config options dictate what is generated in the templates i could take a crack at implementing this - I have contributed to the templates previously - but not connected the build args to whats generated yet - so if there is any guidance or old PRs to look at, I'd be willing to take a crack at it

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the C# generator's enum templates and configuration handling, using the existing zeroBasedEnums option as the comparison point. Determine how configuration values reach generated enum classes and locate the relevant generator tests; done means the new setting works without breaking zeroBasedEnums behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, openapi
Domain
tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.