diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 6a87b9ae9..5cd49343b 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -262,12 +262,12 @@ def _replace_refs( new_schema = deepcopy(schema) for key, value in new_schema.items(): if key == "$ref": - ref_name = schema["$ref"].split("/")[-1] - if ref_name in old_name_to_new_name_map: - new_name = old_name_to_new_name_map[ref_name] - new_schema["$ref"] = REF_TEMPLATE.format(model=new_name) - else: - new_schema["$ref"] = schema["$ref"] + value = schema["$ref"] + if isinstance(value, str): + ref_name = schema["$ref"].split("/")[-1] + if ref_name in old_name_to_new_name_map: + new_name = old_name_to_new_name_map[ref_name] + new_schema["$ref"] = REF_TEMPLATE.format(model=new_name) continue if isinstance(value, dict): new_schema[key] = _replace_refs( diff --git a/tests/test_schema_ref_pydantic_v2.py b/tests/test_schema_ref_pydantic_v2.py new file mode 100644 index 000000000..119b76a52 --- /dev/null +++ b/tests/test_schema_ref_pydantic_v2.py @@ -0,0 +1,72 @@ +from typing import Any + +import pytest +from fastapi import FastAPI +from fastapi.testclient import TestClient +from inline_snapshot import snapshot +from pydantic import BaseModel, ConfigDict, Field + +from tests.utils import needs_pydanticv2 + + +@pytest.fixture(name="client") +def get_client(): + app = FastAPI() + + class ModelWithRef(BaseModel): + ref: str = Field(validation_alias="$ref", serialization_alias="$ref") + model_config = ConfigDict(validate_by_alias=True, serialize_by_alias=True) + + @app.get("/", response_model=ModelWithRef) + async def read_root() -> Any: + return {"$ref": "some-ref"} + + client = TestClient(app) + return client + + +@needs_pydanticv2 +def test_get(client: TestClient): + response = client.get("/") + assert response.json() == {"$ref": "some-ref"} + + +@needs_pydanticv2 +def test_openapi_schema(client: TestClient): + response = client.get("openapi.json") + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "summary": "Read Root", + "operationId": "read_root__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModelWithRef" + } + } + }, + } + }, + } + } + }, + "components": { + "schemas": { + "ModelWithRef": { + "properties": {"$ref": {"type": "string", "title": "$Ref"}}, + "type": "object", + "required": ["$ref"], + "title": "ModelWithRef", + } + } + }, + } + )