Skip to content

Discriminator property uses payload name instead of discriminator value #1016

Closed
@sgrimm

Description

@sgrimm

Description

If a component schema has a discriminator property and mapping, the property's value for each mapped type should be the key from the mapping object. Instead, it is the name of the referenced type.

In the example below:

      discriminator:
        propertyName: operation
        mapping:
          and: '#/components/schemas/AndNodePayload'
          field: '#/components/schemas/FieldNodePayload'

should result in a generated type AndNodePayload with a property operation whose value must be "and". Instead, I get a type AndNodePayload with a property operation whose value must be "AndNodePayload".

OpenAPI

This is an excerpt; full schema is here. This excerpt doesn't validate successfully but the full schema does.

openapi: 3.0.1
paths:
  /api/v1/search:
    post:
      operationId: search
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SearchRequestPayload'
        required: true
components:
  schemas:
    AndNodePayload:
      required:
      - children
      type: object
      allOf:
      - $ref: '#/components/schemas/SearchNodePayload'
      - type: object
        properties:
          children:
            minItems: 1
            type: array
            items:
              $ref: '#/components/schemas/SearchNodePayload'
    FieldNodePayload:
      required:
      - field
      type: object
      allOf:
      - $ref: '#/components/schemas/SearchNodePayload'
      - type: object
        properties:
          field:
            type: string
    SearchNodePayload:
      required:
      - operation
      type: object
      properties:
        operation:
          type: string
      discriminator:
        propertyName: operation
        mapping:
          and: '#/components/schemas/AndNodePayload'
          field: '#/components/schemas/FieldNodePayload'
      oneOf:
      - $ref: '#/components/schemas/AndNodePayload'
      - $ref: '#/components/schemas/FieldNodePayload'
    SearchRequestPayload:
      type: object
      properties:
        search:
          oneOf:
          - $ref: '#/components/schemas/AndNodePayload'
          - $ref: '#/components/schemas/FieldNodePayload'

Generated TS

export interface paths {
  "/api/v1/search": {
    post: operations["search"];
  };
}

export type webhooks = Record<string, never>;

export interface components {
  schemas: {
    AndNodePayload: {
      operation: "AndNodePayload";
    } & Omit<components["schemas"]["SearchNodePayload"], "operation"> & {
      children?: (components["schemas"]["SearchNodePayload"])[];
    };
    FieldNodePayload: {
      operation: "FieldNodePayload";
    } & Omit<components["schemas"]["SearchNodePayload"], "operation"> & {
      field?: string;
    };
    SearchNodePayload: components["schemas"]["AndNodePayload"] | components["schemas"]["FieldNodePayload"];
    SearchRequestPayload: {
      search?: components["schemas"]["AndNodePayload"] | components["schemas"]["FieldNodePayload"];
    };
  };
  responses: never;
  parameters: never;
  requestBodies: never;
  headers: never;
  pathItems: never;
}

export type external = Record<string, never>;

export interface operations {

  search: {
    requestBody: {
      content: {
        "application/json": components["schemas"]["SearchRequestPayload"];
      };
    };
  };
}

*Expected TS

export interface paths {
  "/api/v1/search": {
    post: operations["search"];
  };
}

export type webhooks = Record<string, never>;

export interface components {
  schemas: {
    AndNodePayload: {
      operation: "and";
    } & Omit<components["schemas"]["SearchNodePayload"], "operation"> & {
      children?: (components["schemas"]["SearchNodePayload"])[];
    };
    FieldNodePayload: {
      operation: "field";
    } & Omit<components["schemas"]["SearchNodePayload"], "operation"> & {
      field?: string;
    };
    SearchNodePayload: components["schemas"]["AndNodePayload"] | components["schemas"]["FieldNodePayload"];
    SearchRequestPayload: {
      search?: components["schemas"]["AndNodePayload"] | components["schemas"]["FieldNodePayload"];
    };
  };
  responses: never;
  parameters: never;
  requestBodies: never;
  headers: never;
  pathItems: never;
}

export type external = Record<string, never>;

export interface operations {

  search: {
    requestBody: {
      content: {
        "application/json": components["schemas"]["SearchRequestPayload"];
      };
    };
  };
}

Checklist

  • My OpenAPI schema passes a validator
  • I’m willing to open a PR for this (see CONTRIBUTING.md)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions