From e8b98d21871f64234520c1e770f39e6bfea3b0d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 21 Feb 2026 05:01:31 -0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20JSON=20Schema=20for=20file?= =?UTF-8?q?s,=20use=20`contentMediaType`=20instead=20of=20`format:=20binar?= =?UTF-8?q?y`=20(#14953)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/json-base64-bytes.md | 63 +++++ .../tutorial/json-base64-bytes/image01.png | Bin 0 -> 72638 bytes docs/en/mkdocs.yml | 1 + docs_src/json_base64_bytes/__init__.py | 0 .../json_base64_bytes/tutorial001_py310.py | 46 ++++ fastapi/_compat/v2.py | 19 +- fastapi/datastructures.py | 2 +- pyproject.toml | 1 + .../playwright/json_base64_bytes/image01.py | 37 +++ .../test_file/test_list.py | 20 +- .../test_file/test_optional.py | 8 +- .../test_file/test_optional_list.py | 20 +- .../test_file/test_required.py | 16 +- .../test_json_base64_bytes/__init__.py | 0 .../test_tutorial001.py | 225 ++++++++++++++++++ .../test_request_files/test_tutorial001.py | 4 +- .../test_request_files/test_tutorial001_02.py | 10 +- .../test_request_files/test_tutorial001_03.py | 4 +- .../test_request_files/test_tutorial002.py | 10 +- .../test_request_files/test_tutorial003.py | 10 +- .../test_tutorial001.py | 4 +- 21 files changed, 470 insertions(+), 30 deletions(-) create mode 100644 docs/en/docs/advanced/json-base64-bytes.md create mode 100644 docs/en/docs/img/tutorial/json-base64-bytes/image01.png create mode 100644 docs_src/json_base64_bytes/__init__.py create mode 100644 docs_src/json_base64_bytes/tutorial001_py310.py create mode 100644 scripts/playwright/json_base64_bytes/image01.py create mode 100644 tests/test_tutorial/test_json_base64_bytes/__init__.py create mode 100644 tests/test_tutorial/test_json_base64_bytes/test_tutorial001.py diff --git a/docs/en/docs/advanced/json-base64-bytes.md b/docs/en/docs/advanced/json-base64-bytes.md new file mode 100644 index 0000000000..c0dfec72b9 --- /dev/null +++ b/docs/en/docs/advanced/json-base64-bytes.md @@ -0,0 +1,63 @@ +# JSON with Bytes as Base64 { #json-with-bytes-as-base64 } + +If your app needs to receive and send JSON data, but you need to include binary data in it, you can encode it as base64. + +## Base64 vs Files { #base64-vs-files } + +Consider first if you can use [Request Files](../tutorial/request-files.md){.internal-link target=_blank} for uploading binary data and [Custom Response - FileResponse](./custom-response.md#fileresponse--fileresponse-){.internal-link target=_blank} for sending binary data, instead of encoding it in JSON. + +JSON can only contain UTF-8 encoded strings, so it can't contain raw bytes. + +Base64 can encode binary data in strings, but to do it, it needs to use more characters than the original binary data, so it would normally be less efficient than regular files. + +Use base64 only if you definitely need to include binary data in JSON, and you can't use files for that. + +## Pydantic `bytes` { #pydantic-bytes } + +You can declare a Pydantic model with `bytes` fields, and then use `val_json_bytes` in the model config to tell it to use base64 to *validate* input JSON data, as part of that validation it will decode the base64 string into bytes. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} + +If you check the `/docs`, they will show that the field `data` expects base64 encoded bytes: + +
+ +
+ +You could send a request like: + +```json +{ + "description": "Some data", + "data": "aGVsbG8=" +} +``` + +/// tip + +`aGVsbG8=` is the base64 encoding of `hello`. + +/// + +And then Pydantic will decode the base64 string and give you the original bytes in the `data` field of the model. + +You will receive a response like: + +```json +{ + "description": "Some data", + "content": "hello" +} +``` + +## Pydantic `bytes` for Output Data { #pydantic-bytes-for-output-data } + +You can also use `bytes` fields with `ser_json_bytes` in the model config for output data, and Pydantic will *serialize* the bytes as base64 when generating the JSON response. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} + +## Pydantic `bytes` for Input and Output Data { #pydantic-bytes-for-input-and-output-data } + +And of course, you can use the same model configured to use base64 to handle both input (*validate*) with `val_json_bytes` and output (*serialize*) with `ser_json_bytes` when receiving and sending JSON data. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/en/docs/img/tutorial/json-base64-bytes/image01.png b/docs/en/docs/img/tutorial/json-base64-bytes/image01.png new file mode 100644 index 0000000000000000000000000000000000000000..996732b7499a97cbb7ced1612cd87962ecc3292e GIT binary patch literal 72638 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 DataOutput: + data = "hello".encode("utf-8") + return DataOutput(description="A plumbus", data=data) + + +@app.post("/data-in-out") +def post_data_in_out(body: DataInputOutput) -> DataInputOutput: + return body diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index b83bc1b55b..0535c806f2 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -27,7 +27,7 @@ from pydantic._internal._schema_generation_shared import ( # type: ignore[attr- ) from pydantic._internal._typing_extra import eval_type_lenient from pydantic.fields import FieldInfo as FieldInfo -from pydantic.json_schema import GenerateJsonSchema as GenerateJsonSchema +from pydantic.json_schema import GenerateJsonSchema as _GenerateJsonSchema from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue from pydantic_core import CoreSchema as CoreSchema from pydantic_core import PydanticUndefined @@ -40,6 +40,23 @@ RequiredParam = PydanticUndefined Undefined = PydanticUndefined evaluate_forwardref = eval_type_lenient + +class GenerateJsonSchema(_GenerateJsonSchema): + # TODO: remove when this is merged (or equivalent): https://github.com/pydantic/pydantic/pull/12841 + # and dropping support for any version of Pydantic before that one (so, in a very long time) + def bytes_schema(self, schema: CoreSchema) -> JsonSchemaValue: + json_schema = {"type": "string", "contentMediaType": "application/octet-stream"} + bytes_mode = ( + self._config.ser_json_bytes + if self.mode == "serialization" + else self._config.val_json_bytes + ) + if bytes_mode == "base64": + json_schema["contentEncoding"] = "base64" + self.update_with_validations(json_schema, schema, self.ValidationsMapping.bytes) + return json_schema + + # TODO: remove when dropping support for Pydantic < v2.12.3 _Attrs = { "default": ..., diff --git a/fastapi/datastructures.py b/fastapi/datastructures.py index c04b5f0f39..479e1a7c3b 100644 --- a/fastapi/datastructures.py +++ b/fastapi/datastructures.py @@ -139,7 +139,7 @@ class UploadFile(StarletteUploadFile): def __get_pydantic_json_schema__( cls, core_schema: Mapping[str, Any], handler: GetJsonSchemaHandler ) -> dict[str, Any]: - return {"type": "string", "format": "binary"} + return {"type": "string", "contentMediaType": "application/octet-stream"} @classmethod def __get_pydantic_core_schema__( diff --git a/pyproject.toml b/pyproject.toml index 1e6fda3b1c..92b4739458 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -548,6 +548,7 @@ ignore = [ "docs_src/security/tutorial005_an_py39.py" = ["B904"] "docs_src/security/tutorial005_py310.py" = ["B904"] "docs_src/security/tutorial005_py39.py" = ["B904"] +"docs_src/json_base64_bytes/tutorial001_py310.py" = ["UP012"] [tool.ruff.lint.isort] known-third-party = ["fastapi", "pydantic", "starlette"] diff --git a/scripts/playwright/json_base64_bytes/image01.py b/scripts/playwright/json_base64_bytes/image01.py new file mode 100644 index 0000000000..56c57e1c32 --- /dev/null +++ b/scripts/playwright/json_base64_bytes/image01.py @@ -0,0 +1,37 @@ +import subprocess +import time + +import httpx +from playwright.sync_api import Playwright, sync_playwright + + +# Run playwright codegen to generate the code below, copy paste the sections in run() +def run(playwright: Playwright) -> None: + browser = playwright.chromium.launch(headless=False) + # Update the viewport manually + context = browser.new_context(viewport={"width": 960, "height": 1080}) + page = context.new_page() + page.goto("http://localhost:8000/docs") + page.get_by_role("button", name="POST /data Post Data").click() + # Manually add the screenshot + page.screenshot(path="docs/en/docs/img/tutorial/json-base64-bytes/image01.png") + + # --------------------- + context.close() + browser.close() + + +process = subprocess.Popen( + ["fastapi", "run", "docs_src/json_base64_bytes/tutorial001_py310.py"] +) +try: + for _ in range(3): + try: + response = httpx.get("http://localhost:8000/docs") + except httpx.ConnectError: + time.sleep(1) + break + with sync_playwright() as playwright: + run(playwright) +finally: + process.terminate() diff --git a/tests/test_request_params/test_file/test_list.py b/tests/test_request_params/test_file/test_list.py index 68280fcf32..5332795f4c 100644 --- a/tests/test_request_params/test_file/test_list.py +++ b/tests/test_request_params/test_file/test_list.py @@ -37,7 +37,10 @@ def test_list_schema(path: str): "properties": { "p": { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, "title": "P", }, }, @@ -115,7 +118,10 @@ def test_list_alias_schema(path: str): "properties": { "p_alias": { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, "title": "P Alias", }, }, @@ -221,7 +227,10 @@ def test_list_validation_alias_schema(path: str): "properties": { "p_val_alias": { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, "title": "P Val Alias", }, }, @@ -338,7 +347,10 @@ def test_list_alias_and_validation_alias_schema(path: str): "properties": { "p_val_alias": { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, "title": "P Val Alias", }, }, diff --git a/tests/test_request_params/test_file/test_optional.py b/tests/test_request_params/test_file/test_optional.py index b4dc11a06a..3d1aac25e2 100644 --- a/tests/test_request_params/test_file/test_optional.py +++ b/tests/test_request_params/test_file/test_optional.py @@ -37,7 +37,7 @@ def test_optional_schema(path: str): "properties": { "p": { "anyOf": [ - {"type": "string", "format": "binary"}, + {"type": "string", "contentMediaType": "application/octet-stream"}, {"type": "null"}, ], "title": "P", @@ -109,7 +109,7 @@ def test_optional_alias_schema(path: str): "properties": { "p_alias": { "anyOf": [ - {"type": "string", "format": "binary"}, + {"type": "string", "contentMediaType": "application/octet-stream"}, {"type": "null"}, ], "title": "P Alias", @@ -200,7 +200,7 @@ def test_optional_validation_alias_schema(path: str): "properties": { "p_val_alias": { "anyOf": [ - {"type": "string", "format": "binary"}, + {"type": "string", "contentMediaType": "application/octet-stream"}, {"type": "null"}, ], "title": "P Val Alias", @@ -296,7 +296,7 @@ def test_optional_alias_and_validation_alias_schema(path: str): "properties": { "p_val_alias": { "anyOf": [ - {"type": "string", "format": "binary"}, + {"type": "string", "contentMediaType": "application/octet-stream"}, {"type": "null"}, ], "title": "P Val Alias", diff --git a/tests/test_request_params/test_file/test_optional_list.py b/tests/test_request_params/test_file/test_optional_list.py index a506ec991f..3c211b1e8e 100644 --- a/tests/test_request_params/test_file/test_optional_list.py +++ b/tests/test_request_params/test_file/test_optional_list.py @@ -41,7 +41,10 @@ def test_optional_list_schema(path: str): "anyOf": [ { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, }, {"type": "null"}, ], @@ -116,7 +119,10 @@ def test_optional_list_alias_schema(path: str): "anyOf": [ { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, }, {"type": "null"}, ], @@ -205,7 +211,10 @@ def test_optional_validation_alias_schema(path: str): "anyOf": [ { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, }, {"type": "null"}, ], @@ -301,7 +310,10 @@ def test_optional_list_alias_and_validation_alias_schema(path: str): "anyOf": [ { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, }, {"type": "null"}, ], diff --git a/tests/test_request_params/test_file/test_required.py b/tests/test_request_params/test_file/test_required.py index a0f9d23a6b..22d6c0fffd 100644 --- a/tests/test_request_params/test_file/test_required.py +++ b/tests/test_request_params/test_file/test_required.py @@ -35,7 +35,11 @@ def test_required_schema(path: str): assert app.openapi()["components"]["schemas"][body_model_name] == { "properties": { - "p": {"title": "P", "type": "string", "format": "binary"}, + "p": { + "title": "P", + "type": "string", + "contentMediaType": "application/octet-stream", + }, }, "required": ["p"], "title": body_model_name, @@ -109,7 +113,11 @@ def test_required_alias_schema(path: str): assert app.openapi()["components"]["schemas"][body_model_name] == { "properties": { - "p_alias": {"title": "P Alias", "type": "string", "format": "binary"}, + "p_alias": { + "title": "P Alias", + "type": "string", + "contentMediaType": "application/octet-stream", + }, }, "required": ["p_alias"], "title": body_model_name, @@ -216,7 +224,7 @@ def test_required_validation_alias_schema(path: str): "p_val_alias": { "title": "P Val Alias", "type": "string", - "format": "binary", + "contentMediaType": "application/octet-stream", }, }, "required": ["p_val_alias"], @@ -329,7 +337,7 @@ def test_required_alias_and_validation_alias_schema(path: str): "p_val_alias": { "title": "P Val Alias", "type": "string", - "format": "binary", + "contentMediaType": "application/octet-stream", }, }, "required": ["p_val_alias"], diff --git a/tests/test_tutorial/test_json_base64_bytes/__init__.py b/tests/test_tutorial/test_json_base64_bytes/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/test_tutorial/test_json_base64_bytes/test_tutorial001.py b/tests/test_tutorial/test_json_base64_bytes/test_tutorial001.py new file mode 100644 index 0000000000..4d70bca5f3 --- /dev/null +++ b/tests/test_tutorial/test_json_base64_bytes/test_tutorial001.py @@ -0,0 +1,225 @@ +import importlib + +import pytest +from fastapi.testclient import TestClient +from inline_snapshot import snapshot + +from tests.utils import needs_py310 + + +@pytest.fixture( + name="client", + params=[pytest.param("tutorial001_py310", marks=needs_py310)], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.json_base64_bytes.{request.param}") + + client = TestClient(mod.app) + return client + + +def test_post_data(client: TestClient): + response = client.post( + "/data", + json={ + "description": "A file", + "data": "SGVsbG8sIFdvcmxkIQ==", + }, + ) + assert response.status_code == 200, response.text + assert response.json() == {"description": "A file", "content": "Hello, World!"} + + +def test_get_data(client: TestClient): + response = client.get("/data") + assert response.status_code == 200, response.text + assert response.json() == {"description": "A plumbus", "data": "aGVsbG8="} + + +def test_post_data_in_out(client: TestClient): + response = client.post( + "/data-in-out", + json={ + "description": "A plumbus", + "data": "SGVsbG8sIFdvcmxkIQ==", + }, + ) + assert response.status_code == 200, response.text + assert response.json() == { + "description": "A plumbus", + "data": "SGVsbG8sIFdvcmxkIQ==", + } + + +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/data": { + "get": { + "summary": "Get Data", + "operationId": "get_data_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataOutput" + } + } + }, + } + }, + }, + "post": { + "summary": "Post Data", + "operationId": "post_data_data_post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/DataInput"} + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + }, + }, + "/data-in-out": { + "post": { + "summary": "Post Data In Out", + "operationId": "post_data_in_out_data_in_out_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataInputOutput" + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataInputOutput" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "DataInput": { + "properties": { + "description": {"type": "string", "title": "Description"}, + "data": { + "type": "string", + "contentEncoding": "base64", + "contentMediaType": "application/octet-stream", + "title": "Data", + }, + }, + "type": "object", + "required": ["description", "data"], + "title": "DataInput", + }, + "DataInputOutput": { + "properties": { + "description": {"type": "string", "title": "Description"}, + "data": { + "type": "string", + "contentEncoding": "base64", + "contentMediaType": "application/octet-stream", + "title": "Data", + }, + }, + "type": "object", + "required": ["description", "data"], + "title": "DataInputOutput", + }, + "DataOutput": { + "properties": { + "description": {"type": "string", "title": "Description"}, + "data": { + "type": "string", + "contentEncoding": "base64", + "contentMediaType": "application/octet-stream", + "title": "Data", + }, + }, + "type": "object", + "required": ["description", "data"], + "title": "DataOutput", + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", + }, + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", + }, + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, + }, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", + }, + } + }, + } + ) diff --git a/tests/test_tutorial/test_request_files/test_tutorial001.py b/tests/test_tutorial/test_request_files/test_tutorial001.py index 4d3c35d65d..797225bc2d 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001.py @@ -162,8 +162,8 @@ def test_openapi_schema(client: TestClient): "properties": { "file": { "title": "File", + "contentMediaType": "application/octet-stream", "type": "string", - "format": "binary", } }, }, @@ -175,7 +175,7 @@ def test_openapi_schema(client: TestClient): "file": { "title": "File", "type": "string", - "format": "binary", + "contentMediaType": "application/octet-stream", } }, }, diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02.py b/tests/test_tutorial/test_request_files/test_tutorial001_02.py index f199b992ae..4e3c33818e 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02.py @@ -134,7 +134,10 @@ def test_openapi_schema(client: TestClient): "file": { "title": "File", "anyOf": [ - {"type": "string", "format": "binary"}, + { + "type": "string", + "contentMediaType": "application/octet-stream", + }, {"type": "null"}, ], } @@ -147,7 +150,10 @@ def test_openapi_schema(client: TestClient): "file": { "title": "File", "anyOf": [ - {"type": "string", "format": "binary"}, + { + "type": "string", + "contentMediaType": "application/octet-stream", + }, {"type": "null"}, ], } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03.py b/tests/test_tutorial/test_request_files/test_tutorial001_03.py index ce22c1b5c4..bccc617046 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_03.py @@ -123,7 +123,7 @@ def test_openapi_schema(client: TestClient): "title": "File", "type": "string", "description": "A file read as bytes", - "format": "binary", + "contentMediaType": "application/octet-stream", } }, }, @@ -134,9 +134,9 @@ def test_openapi_schema(client: TestClient): "properties": { "file": { "title": "File", + "contentMediaType": "application/octet-stream", "type": "string", "description": "A file read as UploadFile", - "format": "binary", } }, }, diff --git a/tests/test_tutorial/test_request_files/test_tutorial002.py b/tests/test_tutorial/test_request_files/test_tutorial002.py index ebf76b3a07..123468d48f 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial002.py +++ b/tests/test_tutorial/test_request_files/test_tutorial002.py @@ -195,7 +195,10 @@ def test_openapi_schema(client: TestClient): "files": { "title": "Files", "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, } }, }, @@ -207,7 +210,10 @@ def test_openapi_schema(client: TestClient): "files": { "title": "Files", "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, } }, }, diff --git a/tests/test_tutorial/test_request_files/test_tutorial003.py b/tests/test_tutorial/test_request_files/test_tutorial003.py index f11658d27c..2f554d9489 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial003.py +++ b/tests/test_tutorial/test_request_files/test_tutorial003.py @@ -165,7 +165,10 @@ def test_openapi_schema(client: TestClient): "files": { "title": "Files", "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, "description": "Multiple files as bytes", } }, @@ -178,7 +181,10 @@ def test_openapi_schema(client: TestClient): "files": { "title": "Files", "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, "description": "Multiple files as UploadFile", } }, diff --git a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py index e2462e040b..cc10d8bec5 100644 --- a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py @@ -198,12 +198,12 @@ def test_openapi_schema(client: TestClient): "file": { "title": "File", "type": "string", - "format": "binary", + "contentMediaType": "application/octet-stream", }, "fileb": { "title": "Fileb", + "contentMediaType": "application/octet-stream", "type": "string", - "format": "binary", }, "token": {"title": "Token", "type": "string"}, },