Fix schema for `byte` fields inside JSON (do not add `"format": "binary"`)

This commit is contained in:
Yurii Motov 2026-03-06 18:19:31 +01:00
parent 506d278db7
commit 3405306469
2 changed files with 45 additions and 9 deletions

View File

@ -45,16 +45,25 @@ 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"
is_file_upload = schema.get("metadata", {}).get("fastapi_file_upload", False)
if is_file_upload:
json_schema: JsonSchemaValue = {
"type": "string",
"format": "binary",
"contentMediaType": "application/octet-stream",
}
else:
json_schema["format"] = "binary" # For compatibility with OAS 3.0
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

View File

@ -661,6 +661,32 @@ class Form(Body): # type: ignore[misc]
)
class _FileUploadMarker:
"Pydantic metadata marker to tag bytes CoreSchemas as file uploads."
@classmethod
def __get_pydantic_core_schema__(
cls, source: type[Any], handler: Any
) -> dict[str, Any]:
schema = handler(source)
# Find the inner type schema (if nullable or list)
inner_type_schema = schema
if inner_type_schema.get("type") != "bytes":
if inner_type_schema.get("type") == "list":
inner_type_schema = inner_type_schema["items_schema"]
elif "schema" in inner_type_schema:
inner_type_schema = inner_type_schema["schema"]
if inner_type_schema.get("type") == "list":
inner_type_schema = inner_type_schema["items_schema"]
# If the inner type is bytes, add the file upload marker metadata
if inner_type_schema.get("type") == "bytes":
metadata: dict[str, Any] = inner_type_schema.setdefault("metadata", {})
metadata["fastapi_file_upload"] = True
return schema
class File(Form): # type: ignore[misc]
def __init__(
self,
@ -741,6 +767,7 @@ class File(Form): # type: ignore[misc]
json_schema_extra=json_schema_extra,
**extra,
)
self.metadata.append(_FileUploadMarker())
@dataclass(frozen=True)