OpenAPITools / OpenAPITools/openapi-generator

[BUG][Typescript] Discriminator property name in oneOf is transformed incorrectly

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

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • 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?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

The discriminator property name in oneOf is set to contentType if the content_type is used as a discriminator in the OpenAPI spec.
It would fail in runtime during response deserialization with the error TypeError: typeMap[type].getAttributeTypeMap is not a function.
Same might happen for serialization, didn't test that yet.

We need to make sure "content_type" is used, or that the "content_type" is transformed to "contentType" (might not be desirable).

openapi-generator version

7.11.0-SNAPSHOT
Exists at least since 7.10, possibly earlier.

OpenAPI declaration file content or url
openapi: 3.0.3
info:
  title: Discriminator Bug Example
  version: '1.0.0'
  description: A minimal example to demonstrate the bug with discriminatorName in oneOf template

paths:
  /test:
    get:
      summary: Test endpoint
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VendorInfo'

components:
  schemas:
    VendorInfo:
      title: Vendor Info
      description: |
        The information provided to the system from the vendor. Interpretation of this object is up to the client.
      type: object
      discriminator:
        propertyName: content_type
        mapping:
          application/json: '#/components/schemas/VendorJson'
          text/xml: '#/components/schemas/VendorXml'
      oneOf:
        - $ref: '#/components/schemas/VendorJson'
        - $ref: '#/components/schemas/VendorXml'

    VendorJson:
      type: object
      required:
        - content_type
        - json
        - vendor
      properties:
        content_type:
          type: string
          description: Describes the content-type encoding received from the vendor
          enum:
            - application/json
        json:
          type: object
          description: Data representation in JSON
        vendor:
          type: string
          example: EXAMPLE_VENDOR

    VendorXml:
      type: object
      required:
        - content_type
        - vendor
        - xml
      properties:
        content_type:
          type: string
          description: Describes the content-type encoding received from the vendor
          enum:
            - text/xml
        vendor:
          type: string
          example: EXAMPLE_VENDOR
        xml:
          type: string
          description: Data representation in XML

Generation Details

Generated with:
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -i test.yaml -g typescript -o test-gen/ --additional-properties=disallowAdditionalPropertiesIfNotPresent=false,legacyDiscriminatorBehavior=false,withNodeImports=true,platform=node

Steps to reproduce
  • Generate
  • Check the resulting generated models/VendorInfo.ts

It produces the following:

/**
* The information provided to the system from the vendor. Interpretation of this object is up to the client. 
*/
/**
 * @type VendorInfo
 * Type
 * @export
 */
export type VendorInfo = VendorJson | VendorXml;

/**
* @type VendorInfoClass
    * The information provided to the system from the vendor. Interpretation of this object is up to the client. 
* @export
*/
export class VendorInfoClass {
    static readonly discriminator: string | undefined = "contentType";

    static readonly mapping: {[index: string]: string} | undefined = {
        "application/json": "VendorJson",
        "text/xml": "VendorXml",
        "VendorJson": "VendorJson",
        "VendorXml": "VendorXml",
    };
}

It compiles fine, but will fail runtime since contentType wouldn't exist.

Related issues/PRs

https://github.com/OpenAPITools/openapi-generator/pull/20187

Suggest a fix

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

Reproduce the issue with the provided OpenAPI declaration and generation command, then inspect generated models/VendorInfo.ts. Trace how the OpenAPI discriminator propertyName content_type becomes the generated discriminator value contentType, using related PR #20187 as context. Done means generated TypeScript preserves the discriminator name and response deserialization no longer fails at runtime.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, typescript
Domain
api, tooling
Issue type
Bug
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.