Skip to content

[BUG] [python-fastapi] doesn't support additionalProperties properlyย #19311

@mgoltzsche

Description

@mgoltzsche

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • 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

The python-fastapi generator generates invalid model code when the model's OpenAPI schema specifies additionalProperties:
It lets the generated model class extend the type of the value of additionalProperties.
Also, it generates an additional_properties dict field to hold the additional properties but the generated to_dict method that would map it to the correct transfer representation is not honoured by pydantic v2 (which supports storing additional properties within the model object's __dict__ when model_config.extra=allow is specified).

For instance currently the generator generates the following model code when given a type ExampleObject that specifies a static name property as well as additionalProperties: {"type": "string"}:

example_object.py
from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from pydantic import ConfigDict, StrictStr
from typing import Any, ClassVar, Dict, List
from example.gen.models.str import str
try:
    from typing import Self
except ImportError:
    from typing_extensions import Self

class ExampleObject(str):
    name: StrictStr
    additional_properties: Dict[str, Any] = {}
    __properties: ClassVar[List[str]] = ["name"]

    model_config = {
        "populate_by_name": True,
        "validate_assignment": True,
        "protected_namespaces": (),
    }


    def to_str(self) -> str:
        ...
    def to_json(self) -> str:
        ...
    @classmethod
    def from_json(cls, json_str: str) -> Self:
        ...
    def to_dict(self) -> Dict[str, Any]:
        ...
    @classmethod
    def from_dict(cls, obj: Dict) -> Self:
        ...

Please note:

  • It lets the model class inherit from str (specified by additionalProperties schema) and import the non-existing package example.gen.models.str.
  • It generated an additional_properties dict in addition to the __dict__ that already holds all model fields dynamically under the hood - the latter should be leveraged and is sufficient.
Expectation

Instead, I'd expect the following:

  • It should not inherit the value type specified within the additionalProperties schema.
  • It should not generate an additional additional_properties dict but leverage the built-in __dict__ which is anyway how pydantic v2 supports additional properties.
openapi-generator version

131fd51 # v7.7.0+patch

OpenAPI declaration file content or url
openapi.yaml with additionalProperties schema
openapi: "3.0.1"

info:
  title: Example API
  description: Example API to test additionalProperties support
  version: 1.0.0

servers:
  - url: /

tags:
  - name: example

paths:
  /example:
    get:
      operationId: example
      summary: Example operation
      description: An operation that returns an object with dynamic properties
      tags:
        - example
      responses:
        '200':
          description: Example object
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExampleObject'

components:
  schemas:
    ExampleObject:
      type: object
      properties:
        name:
          type: string
      additionalProperties:
        type: string
      required:
        - name
Generation Details

Generate a python server from the previously listed openapi.yaml file using the python-fastapi generator:

openapi-generator generate -i ./openapi.yaml -g python-fastapi -o ./generated --package-name=example.generated -p sourceFolder= -p fastapiImplementationPackage=example.controller
Steps to reproduce
java -jar ./modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -i ./openapi.yaml -g python-fastapi -o ./generated --package-name=example.generated -p sourceFolder= -p fastapiImplementationPackage=example.controller
Related issues/PRs
Suggest a fix

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions