Skip to content

[BUG][CSHARP][GENERICHOST] Undefined Enum in Generated Converters using oneOf #24397

Description

@NishchhalTenics

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
Description

When generating a C# client using OpenAPI Generator (v7.24), there is a critical issue with oneOf schemas that prevents compilation:

Undefined Generated Type for oneOf String Enum: For oneOf schemas containing a string enum, the generated code references an enum type (e.g., OneOf1Enum) that is not generated anywhere, causing compilation failures.

Impact (Major Blocker)

Compilation fails: The generated code references undefined enums (e.g., OneOf1Enum), preventing the project from compiling.


openapi-generator version

v7.24.0

OpenAPI declaration file content or url
openapi: 3.1.2
info:
  title: Simple API
  version: 1.0.0

paths:
  /hello:
    post:
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HelloResponse'

components:
  schemas:
    HelloResponse:
      type: object
      properties:
        firstCustomProperty:
          oneOf:
            - type: number
            - type: string
        secondCustomProperty:
          oneOf:
            - type: number
            - type: string
              enum: [TEST1, TEST2, TEST3]
        thirdCustomProperty:
          oneOf:
            - $ref: '#/components/schemas/FirstSub'
            - $ref: '#/components/schemas/SecondSub'
    FirstSub:
      type: object
      properties:
        id: { type: string }
        name: { type: string }
    SecondSub:
      type: object
      properties:
        id: { type: number }
        name: { type: string }
        age: { type: number }
Generation Details

Use this config.json:

{
  "packageName": "Tenics.OneOfDemo.Sdk",
  "packageVersion": "1.0.0",
  "targetFramework": "net10.0",
  "library": "generichost",
  "nullableReferenceTypes": true,
  "modelPropertyNaming": "PascalCase"
}

Use this to generate client:

openapi-generator-cli generate \
  -i spec.yaml \
  -g csharp \
  -c config.json \
  -o ./generated

Expected Behavior

The generated C# client should compile successfully.

For a oneOf schema containing an inline string enum:

secondCustomProperty:
  oneOf:
    - type: number
    - type: string
      enum: [TEST1, TEST2, TEST3]

For example, the generated code could contain:

public enum OneOf1Enum
{
    TEST1,
    TEST2,
    TEST3
}

and the converter may reference it:

OneOf1Enum? varString = default;

The exact generated representation is not important as long as all referenced types are generated and the client compiles successfully.

Actual Behavior

  • The generated JSON converter references an enum type that is not generated anywhere in the output. (OneOf1Enum), causing compilation errors.
    The generated file:
    HelloResponseSecondCustomPropertyJsonConverter.cs

contains: (The code snippet only shows the first few relevant lines)

        public override HelloResponseSecondCustomProperty Read(ref Utf8JsonReader utf8JsonReader, Type typeToConvert, JsonSerializerOptions jsonSerializerOptions)
        {
            int currentDepth = utf8JsonReader.CurrentDepth;

            if (utf8JsonReader.TokenType != JsonTokenType.StartObject && utf8JsonReader.TokenType != JsonTokenType.StartArray)
                throw new JsonException();

            JsonTokenType startingTokenType = utf8JsonReader.TokenType;

            decimal? varDecimal = default;
            OneOf1Enum? varString = default; // Compilation error: The type or namespace 'OneOf1Enum' could not be found.
        }

The Entire function is here in case thats relevant too

        public override HelloResponseSecondCustomProperty Read(ref Utf8JsonReader utf8JsonReader, Type typeToConvert, JsonSerializerOptions jsonSerializerOptions)
        {
            int currentDepth = utf8JsonReader.CurrentDepth;

            if (utf8JsonReader.TokenType != JsonTokenType.StartObject && utf8JsonReader.TokenType != JsonTokenType.StartArray)
                throw new JsonException();

            JsonTokenType startingTokenType = utf8JsonReader.TokenType;

            decimal? varDecimal = default;
            OneOf1Enum? varString = default;

            Utf8JsonReader utf8JsonReaderOneOf = utf8JsonReader;
            while (utf8JsonReaderOneOf.Read())
            {
                if (startingTokenType == JsonTokenType.StartObject && utf8JsonReaderOneOf.TokenType == JsonTokenType.EndObject && currentDepth == utf8JsonReaderOneOf.CurrentDepth)
                    break;

                if (startingTokenType == JsonTokenType.StartArray && utf8JsonReaderOneOf.TokenType == JsonTokenType.EndArray && currentDepth == utf8JsonReaderOneOf.CurrentDepth)
                    break;

                if (utf8JsonReaderOneOf.TokenType == JsonTokenType.PropertyName && currentDepth == utf8JsonReaderOneOf.CurrentDepth - 1)
                {
                    Utf8JsonReader utf8JsonReaderDecimal = utf8JsonReader;
                    ClientUtils.TryDeserialize<decimal?>(ref utf8JsonReaderDecimal, jsonSerializerOptions, out varDecimal);

                    Utf8JsonReader utf8JsonReaderString = utf8JsonReader;
                    ClientUtils.TryDeserialize<OneOf1Enum?>(ref utf8JsonReaderString, jsonSerializerOptions, out varString);
                }
            }

            while (utf8JsonReader.Read())
            {
                if (startingTokenType == JsonTokenType.StartObject && utf8JsonReader.TokenType == JsonTokenType.EndObject && currentDepth == utf8JsonReader.CurrentDepth)
                    break;

                if (startingTokenType == JsonTokenType.StartArray && utf8JsonReader.TokenType == JsonTokenType.EndArray && currentDepth == utf8JsonReader.CurrentDepth)
                    break;

                if (utf8JsonReader.TokenType == JsonTokenType.PropertyName && currentDepth == utf8JsonReader.CurrentDepth - 1)
                {
                    string? localVarJsonPropertyName = utf8JsonReader.GetString();
                    utf8JsonReader.Read();

                    switch (localVarJsonPropertyName)
                    {
                        default:
                            break;
                    }
                }
            }

            if (varDecimal != null)
                return new HelloResponseSecondCustomProperty(varDecimal.Value);

            if (varString != null)
                return new HelloResponseSecondCustomProperty(varString.Value);

            throw new JsonException();
        }

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions