openapi-generator icon indicating copy to clipboard operation
openapi-generator copied to clipboard

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

Open AntoineDuComptoirDesPharmacies opened this issue 5 months ago • 1 comments

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.