This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Union produces anyOf instead of oneOf for OpenAPI generation #4959
Comments
While this might be a valid issue (I also encountered this bug and am currently using some ugly workarounds 😬), the problem has nothing to do with |
I ran into this problem as well when using openapi-generator to generate a TypeScript SDK from an My workaround was to modify our openapi schema post-generation using the following code:
|
I followed up with pydantic/pydantic#4335 for a more long-term fix that would cause Pydantic to generate |
What's the status of this? Running into the same issue (different code gen tool). |
Thanks so much for taking this up @MaxwellPayne! We just upgraded to the new pydantic and now "oneOf" is added to the schema in case we have a discriminated union. This also works perfectly with FastAPI, when we use the model beyond the "top level field" of the endpoint (speaking both for request and response). To have the discriminated union as a type in "top level field" (request body, response body), I tried to use typing.Annotated to create a intermediate Type which is discriminated (to provide it as a input to FastAPI). If I use that approach it still provides anyOf instead of oneOf. Not sure if that is a bug or my approach is wrong... Here is a minimal example (fastapi==0.89.1, pydantic==1.10.4) from fastapi import FastAPI, status
from typing import Literal, Union, Annotated
from pydantic import BaseModel, Field
# pydantic schemas
class Mammal(BaseModel):
mammaltest: str
class Cat(Mammal):
pet_type: Literal['cat']
meows: int
class Dog(Mammal):
pet_type: Literal['dog']
barks: float
"""This can directly be used as root field for an endpoint"""
MammalBase = Annotated[Union[Dog, Cat], Field(discriminator="pet_type")]
class MammalContainer(BaseModel):
"""Includes a mammal as a field"""
pet: MammalBase
n: int
# FastApi
app = FastAPI()
@app.post(
"/mammal-container-test/",
response_model=MammalContainer,
description="Test endpoint",
status_code=status.HTTP_200_OK,
)
async def mammal_test(mammal_container: MammalContainer):
"""This works perfect both for request and response model and has oneOf"""
return mammal_container
@app.post(
"/mammal-base-test/",
response_model=MammalBase,
description="Test endpoint",
status_code=status.HTTP_200_OK,
)
async def mammal_test(mammal_base: MammalBase):
"""This one still provides anyOf"""
return mammal_base |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
First Check
Commit to Help
Example Code
Description
Hi all,
Example from https://pydantic-docs.helpmanual.io/usage/types/#discriminated-unions-aka-tagged-unions:
Using the class Pet above in FastAPI to allow either Cat or Dog as an input leads to an OpenAPI.json which makes Pet like (printed as yaml)
both OpenApi (https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/) and the specification https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.2.md#discriminatorObject linked by the pydantic docs (link on top) state that it should be oneOf.
I think it's a pydantic issue, But there was already an issue for pydantic which was closed without resolve:
pydantic/pydantic#656
So I open it here, because it may be more relevant for FastAPI, since it leads to an incorrect OpenAPI file. Let me know if you think differently.
Best
Stefan
Operating System
Linux, Windows
Operating System Details
No response
FastAPI Version
0.75.0
Python Version
Python 3.9.7
Additional Context
No response
The text was updated successfully, but these errors were encountered: