OpenAPI specification produces duplicated types due to swagger.json

Got it — I dug through your attached swagger.json and reproduced why OpenAPI Generator spits out numbered duplicate C# models. Short version: the spec reuses the same title for many inline object schemas (e.g., dozens of different objects all titled EntityMapping), so the generator keeps creating classes with the same base name and appends indexes (EntityMapping, EntityMapping1, EntityMapping2, …). Some of those inline schemas are genuinely identical across paths, so the generated classes are also identical. The fix is to stop reusing the same title on inline objects and/or hoist those inline schemas into uniquely named components referenced by $ref.

Below is a comprehensive bug report you can hand to the API/spec owners.

1 - What is it about

Numbered duplicate model classes are generated from the OpenAPI spec because the spec uses the same title for many inline object schemas. The worst offender is title: "EntityMapping" reused across multiple request bodies (often under oneOf), even when the object shapes differ by the ids structure — and sometimes when they are identical across endpoints. This causes openapi-generator-cli (C# target) to generate multiple classes with the same base name and an index suffix to avoid collisions (e.g., EntityMapping, EntityMapping1, EntityMapping2, …).

Examples from the spec:

  • Multiple inline objects with title: "EntityMapping" for relationships like (TestCase,TestRun), (Comment,TestCase), (Blob,Comment), etc., under .../mapping/bulk/... endpoints.
  • The same (Blob,Comment) mapping appears under multiple resources, repeating title: "EntityMapping" and the same structure (so the generated classes are identical).
  • Other repeated titles on inline schemas (not components) include ByKeys, ByKeysValue, and FkIdsNullable, which also show up in multiple places, encouraging duplicate class generation.

2 - Environment

  • Spec: swagger.json (OpenAPI 3.0.3) from Testiny (attached)

  • Generator: OpenAPI Generator (CLI)

  • Command (provided):

    openapi-generator-cli.exe generate -g csharp -o testiny-api-client-csharp -i https://app.testiny.io/api/v1/swagger.json --additional-properties=apiName=TestinyClient,library=restsharp,netCoreProjectFile=true,targetFramework=netstandard2.1,useDateTimeForDate=true,useVirtualForHooks=true --model-package models --package-name TestinyClient
    
  • Target: C# (-g csharp) with RestSharp library

3 - Steps to reproduce

  1. Run the exact CLI command above against the attached swagger.json.
  2. Inspect the generated models folder (e.g., testiny-api-client-csharp/src/TestinyClient/Models).
  3. Observe multiple types with the same base name plus numeric suffix (e.g., EntityMapping.cs, EntityMapping1.cs, EntityMapping2.cs, …).

4 - Expected result

  • Each logically distinct schema produces exactly one C# class.
  • If the same structure appears in multiple places in the spec, it should resolve to the same class (via a single $ref-named component).
  • No numbered duplicate models.

5 - Actual result

  • The generator creates many classes with the same base name and numeric suffixes (e.g., EntityMapping, EntityMapping1, EntityMapping2, …).

  • In several cases, those classes are identical (because the inline schema is repeated verbatim across different endpoints), but duplication still occurs due to the repeated title on inline schemas.

  • Root cause in the spec: reused inline titles (e.g., EntityMapping) across many different object definitions under oneOf arrays in mapping endpoints. Examples:

    • /testcase/mapping/bulk/{otherEntities}: many items objects titled EntityMapping (e.g., (TestCase,TestRun), (Comment,TestCase), (Blob,TestCase), …).
    • /testplan/mapping/bulk/{otherEntities}: repeats the same pattern with title: "EntityMapping".
    • /comment/mapping/bulk/{otherEntities}: again reuses title: "EntityMapping"; also includes duplicates like (Blob,Comment) seen elsewhere.
    • Identical (Blob,Comment) mapping shape appears in more than one place (same properties/required), all titled EntityMapping.
    • Repeated inline titles ByKeys, ByKeysValue, FkIdsNullable also appear in multiple contexts, further encouraging name collisions.

6 - Error logs and or visual proof

  • The generator typically doesn’t error; it silently disambiguates by adding numeric suffixes to the model names.

  • Spec excerpts showing the issue (proof):

    • Reused inline title: "EntityMapping" (mapping payloads), e.g. (TestCase,TestRun) under /testcase/mapping/bulk/{otherEntities}.
    • Reused inline title: "EntityMapping" for (Comment,TestCase) under the same family of endpoints.
    • The exact same (Blob,Comment) mapping object (identical shape) appears in multiple places, always titled EntityMapping.
    • Repeated inline titles for helper schemas like ByKeys, ByKeysValue, and FkIdsNullable.

Where and how to fix this in the source swagger.json

Principle: Inline object schemas with the same title should not be reused across different shapes. Prefer componentized schemas with unique names and $refs everywhere they’re used.

  1. Componentize each mapping payload with a unique name
    Instead of repeating inline objects titled EntityMapping, define them once under components/schemas and reuse via $ref. For example:
components:
  schemas:
    TestCaseTestRunMapping:
      type: object
      properties:
        ids:
          type: object
          properties:
            testcase_id: { type: integer }
            testrun_id:  { type: integer }
          required: [testcase_id, testrun_id]
        mapped:
          $ref: '#/components/schemas/TestRunTestCaseValues'
      required: [ids]

    BlobCommentMapping:
      type: object
      properties:
        ids:
          type: object
          properties:
            blob_id:    { type: integer }
            comment_id: { type: integer }
          required: [blob_id, comment_id]
        mapped:
          $ref: '#/components/schemas/BlobCommentValues'
      required: [ids]

Then replace every items: { title: "EntityMapping", type: object, ... } occurrence with:

items:
  $ref: '#/components/schemas/TestCaseTestRunMapping'  # or BlobCommentMapping, etc.

This guarantees one class per logical payload and eliminates numbering.

  1. Remove/avoid generic title: "EntityMapping" on inline schemas
    If you must keep inline schemas, either omit title (so the generator derives a unique name per location) or use unique, descriptive titles per shape, e.g., EntityMapping_TestCase_TestRun. The current reuse of the same title across different shapes is what triggers name collisions and numeric suffixes. See the repeated title: "EntityMapping" blocks:

  2. Do the same for helper inlines like ByKeys, ByKeysValue, FkIdsNullable
    Define them once under components/schemas (with those names) and reference them wherever needed. Right now they are also introduced via inline schemas carrying the same title in different spots, which can produce additional duplicate models.

  3. (Optional clean-up) Factor out repeated “FindResult” response shapes
    Many 200 responses embed the same { data: [], meta: {} } structure inline. While this doesn’t usually cause numbered duplicates, moving them to components (e.g., FindResultProject, FindResultTestCase) improves consistency and reduces generated noise. See repeated inline list responses in find endpoints.


Why this happens (generator behavior)

OpenAPI Generator uses heuristics to name models for inline schemas. If the inline schema has a title, it often becomes the model name. Reusing the same title for many different inline schemas forces the generator to disambiguate by appending numbers (EntityMapping1, EntityMapping2, …). When two inline schemas are structurally identical but defined separately, you can still get duplicate classes because, to the generator, they are different definitions with the same title, not a single $ref-reused schema.


Bug report was generated with the help of AI. I was a bit short-on-time in this issue.

It is however a fact, that I get a client result which contains unnecessary class duplicates due to a misconfiguration in the swagger.json.

We’ve shipped another update for the OpenAPI specification with the recent v1.27.0 release.

Best regards,
Alex

Hello Nikolaus,

Thank you for your report.
We’ll look into this when possible.

Regards,
Michael