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 sametitle
for many inline object schemas (e.g., dozens of different objects all titledEntityMapping
), 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 sametitle
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, repeatingtitle: "EntityMapping"
and the same structure (so the generated classes are identical). - Other repeated
title
s on inline schemas (not components) includeByKeys
,ByKeysValue
, andFkIdsNullable
, 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
- Run the exact CLI command above against the attached
swagger.json
. - Inspect the generated models folder (e.g.,
testiny-api-client-csharp/src/TestinyClient/Models
). - 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
title
s (e.g.,EntityMapping
) across many different object definitions underoneOf
arrays in mapping endpoints. Examples:/testcase/mapping/bulk/{otherEntities}
: manyitems
objects titled EntityMapping (e.g.,(TestCase,TestRun)
,(Comment,TestCase)
,(Blob,TestCase)
, …)./testplan/mapping/bulk/{otherEntities}
: repeats the same pattern withtitle: "EntityMapping"
./comment/mapping/bulk/{otherEntities}
: again reusestitle: "EntityMapping"
; also includes duplicates like(Blob,Comment)
seen elsewhere.- Identical
(Blob,Comment)
mapping shape appears in more than one place (same properties/required), all titledEntityMapping
. - 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 titledEntityMapping
. - Repeated inline titles for helper schemas like
ByKeys
,ByKeysValue
, andFkIdsNullable
.
- Reused inline
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 $ref
s everywhere they’re used.
- Componentize each mapping payload with a unique name
Instead of repeating inline objects titledEntityMapping
, define them once undercomponents/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.
-
Remove/avoid generic
title: "EntityMapping"
on inline schemas
If you must keep inline schemas, either omittitle
(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 sametitle
across different shapes is what triggers name collisions and numeric suffixes. See the repeatedtitle: "EntityMapping"
blocks: -
Do the same for helper inlines like
ByKeys
,ByKeysValue
,FkIdsNullable
Define them once undercomponents/schemas
(with those names) and reference them wherever needed. Right now they are also introduced via inline schemas carrying the sametitle
in different spots, which can produce additional duplicate models. -
(Optional clean-up) Factor out repeated “FindResult” response shapes
Many200
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 infind
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.