From fa7cd85f77038b56536b25f43d5b58e456e59be4 Mon Sep 17 00:00:00 2001 From: "Julio C. Galindo" <54072664+stickM4N@users.noreply.github.com> Date: Wed, 23 Jul 2025 15:43:21 +0200 Subject: [PATCH 1/3] feat: add possibility to override json schema generator class --- fastapi/openapi/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 808646cc2..4c8530d34 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -489,6 +489,7 @@ def get_openapi( contact: Optional[Dict[str, Union[str, Any]]] = None, license_info: Optional[Dict[str, Union[str, Any]]] = None, separate_input_output_schemas: bool = True, + schema_generator: Optional[GenerateJsonSchema] = None, ) -> Dict[str, Any]: info: Dict[str, Any] = {"title": title, "version": version} if summary: @@ -510,7 +511,7 @@ def get_openapi( operation_ids: Set[str] = set() all_fields = get_fields_from_routes(list(routes or []) + list(webhooks or [])) model_name_map = get_compat_model_name_map(all_fields) - schema_generator = GenerateJsonSchema(ref_template=REF_TEMPLATE) + schema_generator = schema_generator or GenerateJsonSchema(ref_template=REF_TEMPLATE) field_mapping, definitions = get_definitions( fields=all_fields, schema_generator=schema_generator, From 8cdb9637c79711e5ee393f0afe7c7f34f6376117 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Fri, 1 Aug 2025 11:07:39 +0200 Subject: [PATCH 2/3] Add test --- tests/test_openapi_custom_schema_generator.py | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 tests/test_openapi_custom_schema_generator.py diff --git a/tests/test_openapi_custom_schema_generator.py b/tests/test_openapi_custom_schema_generator.py new file mode 100644 index 000000000..62fb15399 --- /dev/null +++ b/tests/test_openapi_custom_schema_generator.py @@ -0,0 +1,81 @@ +import pytest +from fastapi import FastAPI +from fastapi._compat import PYDANTIC_V2, GenerateJsonSchema +from fastapi.openapi.utils import get_openapi + +app = FastAPI() + + +@app.get("/") +def read_root(): + pass # pragma: no cover + + +# Custom schema generator that does nothing but tracks if it was called +class CustomJsonSchemaGenerator(GenerateJsonSchema): + def __init__(self): + super().__init__() + self.called = False + + def generate_definitions(self, *args, **kwargs): + self.called = True + return super().generate_definitions(*args, **kwargs) + + +def test_custom_schema_generator_called(): + custom_schema_generator = CustomJsonSchemaGenerator() + get_openapi( + title=app.title, + version=app.version, + routes=app.routes, + schema_generator=custom_schema_generator, + ) + + if PYDANTIC_V2: + assert custom_schema_generator.called is True + else: + assert ( # Pydantic v1 does not use custom schema generators + custom_schema_generator.called is False + ) + + +@pytest.mark.parametrize("use_custom_schema_generator", [True, False]) +def test_custom_schema_generator_openapi(use_custom_schema_generator: bool): + custom_schema_generator = ( + CustomJsonSchemaGenerator() if use_custom_schema_generator else None + ) + openapi = get_openapi( + title=app.title, + version=app.version, + routes=app.routes, + schema_generator=custom_schema_generator, + ) + + assert openapi == OPENAPI_SCHEMA + + +OPENAPI_SCHEMA = { + "info": { + "title": "FastAPI", + "version": "0.1.0", + }, + "openapi": "3.1.0", + "paths": { + "/": { + "get": { + "operationId": "read_root__get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {}, + }, + }, + "description": "Successful Response", + }, + }, + "summary": "Read Root", + }, + }, + }, +} From 330e14bc10c1101813649e962bd2dcd779223e35 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Fri, 1 Aug 2025 11:14:31 +0200 Subject: [PATCH 3/3] Fix test --- tests/test_openapi_custom_schema_generator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_openapi_custom_schema_generator.py b/tests/test_openapi_custom_schema_generator.py index 62fb15399..b547992fc 100644 --- a/tests/test_openapi_custom_schema_generator.py +++ b/tests/test_openapi_custom_schema_generator.py @@ -1,6 +1,7 @@ import pytest from fastapi import FastAPI from fastapi._compat import PYDANTIC_V2, GenerateJsonSchema +from fastapi.openapi.constants import REF_TEMPLATE from fastapi.openapi.utils import get_openapi app = FastAPI() @@ -14,7 +15,7 @@ def read_root(): # Custom schema generator that does nothing but tracks if it was called class CustomJsonSchemaGenerator(GenerateJsonSchema): def __init__(self): - super().__init__() + super().__init__(ref_template=REF_TEMPLATE) self.called = False def generate_definitions(self, *args, **kwargs):