Skip to content

Deeply nested Pydantic schemas appear as null in /docs example values #189

@migduroli

Description

@migduroli

Summary

When using a Pydantic model with multiple levels of nesting (more than two layers deep) as a request body or response model, the example value generated for the OpenAPI documentation (/docs) is incomplete.

Reproduce steps

Description

When using a Pydantic model with multiple levels of nesting (more than two layers deep) as a request body or response model, the example value generated for the OpenAPI documentation (/docs/) is incomplete.

Specifically, the schema generation logic stops expanding the example structure after the second level of nesting. Any fields at the third level and beyond are rendered with a value of null, instead of showing their complete, nested structure. This makes it difficult for users of the API to understand the full data contract from the documentation's example view.

Steps to Reproduce

The following minimal application demonstrates the issue.

  1. Save the code below as app.py:
import typing as t

import pydantic

import flama
from flama import Flama, schemas

app = Flama(
    openapi={
        "info": {
            "title": "Puppy Register",  # API title
            "version": "0.1",  # API version
            "description": "A register of puppies",  # API description
        }
    },
    schema="/schema/",  # Path to expose OpenAPI schema
    docs="/docs/",  # Path to expose Docs application
)


class FooBarSchema(pydantic.BaseModel):
    x: float | None


class BarSchema(pydantic.BaseModel):
    foobar: FooBarSchema


class FooSchema(pydantic.BaseModel):
    bar: BarSchema


class PuppyMeta(pydantic.BaseModel):
    foo: FooSchema


class Puppy(pydantic.BaseModel):
    id: int
    name: str
    age: int

    meta: PuppyMeta


app.schema.register_schema("Puppy", Puppy)


def home():
    return {"hello": "world"}


def list_puppies(name: t.Optional[str] = None) -> t.Annotated[list[schemas.SchemaType], schemas.SchemaMetadata(Puppy)]:
    ...


def create_puppy(
    puppy: t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(Puppy)],
) -> t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(Puppy)]:
    ...


app.add_route("/puppy/", list_puppies, methods=["GET"])
app.add_route("/puppy/", create_puppy, methods=["POST"])

if __name__ == "__main__":
    flama.run(flama_app=app, server_host="0.0.0.0", server_port=8080)
  1. Run the application, for example: flama run --server-reload app:app.
  2. Open your browser and navigate to the docs UI at http://127.0.0.1:8000/docs/.
  3. Look at the example value for the 200 OK response.

Expected Behavior

The example JSON in the /docs/ UI should be fully expanded to show the structure of all nested models, regardless of the nesting depth. The expected example value should look like this:

{
  "id": 0,
  "name": "string",
  "age": 0,
  "meta": {
    "foo": {
      "bar": {
        "foobar": {
          "x": 1.0
        }
      }
    }
  }
}

Actual Behavior

The example JSON is only expanded up to the second level of nesting. The field at the third level (bar) is shown with a value of null, incorrectly hiding the deeper structure (foobar and x). The actual rendered example is:

{
  "id": 0,
  "name": "string",
  "age": 0,
  "meta": {
    "foo": {
      "bar": null
    }
  }
}

Schema library

Pydantic

Models library

None

Error logs

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions