OpenAPITools / OpenAPITools/openapi-generator

[BUG] [python-fastapi] Bad management of anyOf type while using as server

Open
#19,453 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

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

When generating a FastAPI server with routes that accept anyOf models as request JSON body param, the generated models do not support decoding these values.

openapi-generator version

v7.8.0

OpenAPI declaration file content or url
Sample of our openapi : 

requestBody:
  required: true
  content:
    application/json:
      schema:
        $ref: '#/components/schemas/AssemblyCreationParameters'

AssemblyCreationParameters:
  type: object
  properties:
    ownerId:
      type: integer
      format: int64
    factory:
      $ref: '#/components/schemas/AnyFactory'
  required:
    - ownerId
    - factory

AnyFactory:
  oneOf:
    - $ref: '#/components/schemas/ProductUpsertFactory'
    - $ref: '#/components/schemas/SaleOfferUpsertFactory'
    - $ref: '#/components/schemas/OfferPlanificationFactory'
  discriminator:
    propertyName: type
    mapping:
      PRODUCT_UPSERT: '#/components/schemas/ProductUpsertFactory'
      SALE_OFFER_UPSERT: '#/components/schemas/SaleOfferUpsertFactory'
      OFFER_PLANIFICATION: '#/components/schemas/OfferPlanificationFactory'

ProductUpsertFactory:
  allOf:
    - $ref: '#/components/schemas/FactoryType'
    - $ref: '#/components/schemas/Product'

The JSON Body sent through request :

{
    "ownerId": 2,
    "factory": {
        "type": "OFFER_PLANIFICATION",
        "product": {
            "cip": "545"
        },
        "distribution": {
            "soldBy": 4
        },
        "reference": "ojojp"
    }
}
Generation Details

Run 'python-fastapi' codegen with all default properties / parameters.

The generated anyOf model will have the following constructor :

  def __init__(self, *args, **kwargs) -> None:
        if args:
            if len(args) > 1:
                raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`")
            if kwargs:
                raise ValueError("If a position argument is used, keyword arguments cannot be used.")
            super().__init__(actual_instance=args[0])
        else:
            super().__init__(**kwargs)

When a request body is received on the server, the constructor is called with 👍

  • args : ()
  • kwargs : Every fields of the object, for example :
    dict({ "type": "ProductUpsertFactory", "cip": "1234", [...] })

Final object have every field empty because we enter in the 'else' condition and init is called with every args of kwargs.

Steps to reproduce
  1. Run the 'fast-api' generator as a 'SERVER' with anyOf definition using discriminator
  2. Run the server and try to send a anyOf object in the body of the payload
  3. The model in the controller is empty
Related issues/PRs

None

Suggest a fix

Use the native discriminator feature of python-fastapi.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the python-fastapi server generator's handling of generated anyOf models with discriminators, using the OpenAPI declaration and JSON request body in this issue to reproduce the behavior. Run the generated server and send the anyOf payload; done means the controller receives a populated model with the selected discriminator variant's fields.

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.