Skip to content

[BUG] [PYTHON-FASTAPI] required request body generates an optional body #21236

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

Open
5 of 6 tasks
jorgehermo9 opened this issue May 7, 2025 · 1 comment
Open
5 of 6 tasks

Comments

@jorgehermo9
Copy link

jorgehermo9 commented May 7, 2025

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

When defining a requestBody as required via the requestBody.required: true property in openapi (https://swagger.io/docs/specification/v3_0/describing-request-body/describing-request-body/#requestbody-content-and-media-types), I expect the generated server to generate a required body. However, the generated server sets the default value of that parameter to None, so FastAPI marks that body as optional.

Pydantic reference: https://fastapi.tiangolo.com/tutorial/body/#create-your-data-model
Image

openapi-generator version

7.12.0

I don't think this is a regression, as looking through the git history, didn't seem to have ever worked

OpenAPI declaration file content or url
openapi: 3.0.1
info:
  title: Sample API
  version: 1.0.0
paths:
  /pets:
    post:
      summary: Add a new pet
      requestBody:
        description: Optional description in *Markdown*
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Pet"
      responses:
        "201":
          description: Created

components:
  schemas:
    Pet:
      type: object
      required:
        - name
      properties:
        name:
          type: string
        tag:
          type: string
Generation Details
openapi-generator generate -i openapi.yml -g python-fastapi -o server

This generates something like this

@router.post(
    "/pets",
    responses={
        201: {"description": "Created"},
    },
    tags=["default"],
    summary="Add a new pet",
    response_model_by_alias=True,
)
async def pets_post(
    pet: Annotated[Pet, Field(description="Optional description in *Markdown*")] = Body(None, description="Optional description in *Markdown*"),
) -> None:

note the pet field value: Body(None, description="Optional description in *Markdown*"), the Body has None as a default argument, so FastAPI marks that as optional.
The expected field value should be something like just Body(description="Optional description in *Markdown*") so pydantic marks that as required

Note: the Path param uses something like Path(..., description="description"), pydantic used to require ... as an argument to mark the field as a required, but this is not required in pydantic's newer versions, just omit that first default argument. See: https://stackoverflow.com/a/74884189

Related issues/PRs

Something similar has been done previously with the Path param #17532, but this fix is not exactly the same (the parameter should not always be required as the path param, but rely on requestBody.required property to set the default value to None or not)

Suggest a fix

The problem is in this file:
https://github.com/OpenAPITools/openapi-generator/blob/f2813716fb815dae0e5bc6b2219452b3303f4934/modules/openapi-generator/src/main/resources/python-fastapi/endpoint_argument_definition.mustache

And in the definition of the Body parameter

Image

When settings the first argument as None, we must check if the requestBody.required property is set to true, and in that case, omit the first argument entirely.

@jorgehermo9
Copy link
Author

jorgehermo9 commented May 7, 2025

I'm open to contribute to fix this, but I may need help to know how can I access the requestBody.required property inside the .mustache file. In which template variable should be that available?

I see this

Should that required attribute be accessible in the mustache file and maybe we can do something like {{^required}}None{{/required}}?

@jorgehermo9 jorgehermo9 changed the title [BUG] [PYTHON-FASTAPI] requestBody.required = true generates and optional body [BUG] [PYTHON-FASTAPI] required request body generates an optional body May 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant