OpenAPITools / OpenAPITools/openapi-generator
[BUG] Bug Report / Feature Request: Improve oneOf Handling for FastAPI/Pydantic
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
I am facing a similar issue:
🐞 Bug Report / Feature Request: Improve oneOf Handling for FastAPI/Pydantic
Summary:
The current OpenAPI Generator implementation for Python (FastAPI + Pydantic) generates wrapper classes for oneOf schemas (e.g., CaseEmbeddingsInputPayloadCaseInformation) that rely on a field like actual_instance and custom deserialization logic. However, this structure is incompatible with FastAPI's request parsing flow and Pydantic's native validation pipeline, leading to broken or non-functional schema resolution.{ "title": "Case Embeddings Input", "type": "object", "required": ["case_information"], "properties": { "case_information": { "oneOf": [ { "$ref": "./case_information_with_case_number.json" }, { "$ref": "./case_information_with_id_v2.json" } ] } } }and my individual schemas are:
{ "title": "Case Information with case number", "type": "object", "required": [ "partner_id", "case_number", "case_category", "case_description" ], "properties": { "partner_id": { "type": "string", "minLength": 1, "maxLength": 30, "description": "Partner Id" }, "case_number": { "type": "string", "minLength": 1, "maxLength": 30, "description": "Case Id" }, "id": { "type": "string", "minLength": 1, "maxLength": 30, "description": "Case Id", "nullable": true }, "case_category": { "type": "string", "minLength": 1, "maxLength": 5000, "description": "Case Category" }, "case_description": { "type": "string", "minLength": 1, "maxLength": 5000, "description": "Case Description" }, "case_language_identifier": { "type": "string", "minLength": 1, "maxLength": 10, "description": "Case Language Identifier" } } }Schema 2
{ "title": "Case Information with id", "type": "object", "required": [ "partner_id", "id", "case_category", "case_description" ], "properties": { "partner_id": { "type": "string", "minLength": 1, "maxLength": 30, "description": "Partner Id" }, "case_number": { "type": "string", "minLength": 1, "maxLength": 30, "description": "Case Id", "nullable": true }, "id": { "type": "string", "minLength": 1, "maxLength": 30, "description": "Case Id" }, "case_category": { "type": "string", "minLength": 1, "maxLength": 5000, "description": "Case Category" }, "case_description": { "type": "string", "minLength": 1, "maxLength": 5000, "description": "Case Description" }, "case_language_identifier": { "type": "string", "minLength": 1, "maxLength": 10, "description": "Case Language Identifier" } } }which produces
class CaseEmbeddingsInputPayload(BaseModel): case_information: Optional[CaseEmbeddingsInputPayloadCaseInformation] = NoneWhere CaseEmbeddingsInputPayloadCaseInformation wraps the oneOf logic using an actual_instance field and custom init() or from_json() methods.
However:
- FastAPI does not invoke init() or from_json() during request parsing.
- The payload is passed as keyword arguments, which do not match the expected structure.
- As a result, actual_instance is never set, and validation fails silently. unless we manually set {"actual_instance": **kwargs"} in the init def.
- The input ends up being None, even though it matches one of the schemas.
Instead of generating a wrapper class, emit a native Python Union type:
class CaseEmbeddingsInputPayload(BaseModel): case_information: Union[CaseInformationWithCaseNumber, CaseInformationWithIdV2]which works.
Originally posted by @lek18 in #21892
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
No repository files or tests are named. Start by tracing the generated CaseEmbeddingsInputPayloadCaseInformation wrapper, especially actual_instance, init(), and from_json(), alongside the FastAPI request parsing path. Done means oneOf fields are generated as native Python Union types and valid requests pass Pydantic validation without manual actual_instance handling.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- fastapi, python
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100