據(jù)(bytes 字段實戰(zhàn)))
FastAPI 進階在 JSON 中用 Base64 傳輸二進制數(shù)據(jù)bytes 字段實戰(zhàn)【免費下載鏈接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production項目地址: https://gitcode.com/GitHub_Trending/fa/fastapi本篇指南講解 FastAPI 中一個進階但非常實用的場景當你的接口必須接收和發(fā)送 JSON 數(shù)據(jù)、其中又需要攜帶二進制內容bytes時如何利用 Pydantic 的val_json_bytes與ser_json_bytes配置把二進制數(shù)據(jù)安全地以 base64 編碼嵌入 JSON 請求體與響應體。讀完本文你將掌握 base64 方案與文件上傳/下載方案的取舍原則、bytes字段模型配置的完整寫法以及 FastAPI 源碼中 OpenAPI Schema 是如何自動生成contentEncoding: base64聲明的底層機制。何時需要用 Base64 而不是文件如果你的應用需要接收和發(fā)送 JSON 數(shù)據(jù)但其中必須包含二進制數(shù)據(jù)就可以把這些二進制數(shù)據(jù)編碼為 base64 字符串來傳輸。在選擇方案之前先評估是否可以直接使用 請求文件 來上傳二進制數(shù)據(jù)、使用 自定義響應 – FileResponse 來下發(fā)二進制數(shù)據(jù)而不是把二進制內容編碼進 JSON。兩者的取舍依據(jù)如下JSON 只能包含 UTF-8 編碼的字符串因此它無法承載原始字節(jié)raw bytesBase64 可以把二進制數(shù)據(jù)編碼成字符串但代價是需要比原始二進制數(shù)據(jù)更多的字符通常膨脹約 1/3因此在傳輸效率上一般不如直接傳文件只有當你確實必須把二進制數(shù)據(jù)內嵌在 JSON 中、且無法改用文件方案時才使用 base64。用 Pydanticbytes字段接收輸入數(shù)據(jù)聲明一個帶bytes字段的 Pydantic 模型并在模型配置中設置val_json_bytes即可告訴 Pydantic在校驗validate輸入的 JSON 數(shù)據(jù)時使用 base64。校驗過程中base64 字符串會被自動解碼為字節(jié)對象。完整示例見 docs_src/json_base64_bytes/tutorial001_py310.py其中接收端模型為from fastapi import FastAPI from pydantic import BaseModel class DataInput(BaseModel): description: str data: bytes model_config {val_json_bytes: base64} app FastAPI() app.post(/data) def post_data(body: DataInput): content body.data.decode(utf-8) return {description: body.description, content: content}啟動應用后訪問/docsSwagger UI 會展示字段data期望接收 base64 編碼的字節(jié)此時可以發(fā)送如下請求{ description: Some data, data: aGVsbG8 }提示aGVsbG8就是字符串hello的 base64 編碼。Pydantic 會解碼這個 base64 字符串并在模型的data字段中把原始字節(jié)交給你。隨后你會收到類似這樣的響應{ description: Some data, content: hello }這里的關鍵點在于端點函數(shù)拿到的body.data已經(jīng)是解碼后的bytes類型示例中再用.decode(utf-8)轉回字符串base64 編解碼完全由 Pydantic 在模型邊界處自動完成業(yè)務代碼無需手動調用任何base64模塊。用 Pydanticbytes字段輸出數(shù)據(jù)對于輸出數(shù)據(jù)可以在模型配置中使用ser_json_bytes。Pydantic 在生成 JSON 響應時會把字節(jié)序列化serialize為 base64 字符串class DataOutput(BaseModel): description: str data: bytes model_config {ser_json_bytes: base64} app.get(/data) def get_data() - DataOutput: data hello.encode(utf-8) return DataOutput(descriptionA plumbus, datadata)響應體中data字段就會以aGVsbG8這樣的 base64 字符串形式返回。倉庫中的測試 tests/test_tutorial/test_json_base64_bytes/test_tutorial001.py 正是如此斷言的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}測試同時覆蓋了輸入方向發(fā)送SGVsbG8sIFdvcmxkIQ解碼為Hello, World!驗證了這套機制在真實請求/響應鏈路中的端到端行為。同一模型同時處理輸入和輸出當然你也可以配置同一個模型讓 base64 同時用于輸入校驗和輸出序列化class DataInputOutput(BaseModel): description: str data: bytes model_config { val_json_bytes: base64, ser_json_bytes: base64, } app.post(/data-in-out) def post_data_in_out(body: DataInputOutput) - DataInputOutput: return body此時請求體里的 base64 字符串會被解碼成bytes傳入端點端點把同一個模型對象返回后bytes又會以 base64 形式序列化進響應。上述測試文件中的test_post_data_in_out驗證了這一回環(huán)發(fā)送SGVsbG8sIFdvcmxkIQ響應體中data原樣返回同一 base64 字符串。源碼視角OpenAPI Schema 是怎么知道要聲明 base64 的一個值得注意的細節(jié)是配置val_json_bytes/ser_json_bytes后OpenAPI 文檔會自動為bytes字段生成contentEncoding: base64和contentMediaType: application/octet-stream聲明/docs界面因此能正確提示該字段期望 base64 字符串。從上面的測試快照test_openapi_schema可以看到生成的 Schema 片段data: { type: string, contentEncoding: base64, contentMediaType: application/octet-stream, title: Data }這一行為來自 FastAPI 對 Pydantic JSON Schema 生成器的定制覆蓋位于 fastapi/_compat/v2.pyclass GenerateJsonSchema(_GenerateJsonSchema): 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從這段源碼可以看出兩個要點FastAPI 重寫了 Pydantic 的bytes_schema方法先按bytes的默認語義生成type: stringcontentMediaType: application/octet-stream然后根據(jù)當前模式校驗模式讀val_json_bytes、序列化模式讀ser_json_bytes當配置值為base64時追加contentEncoding: base64聲明。也就是說Schema 聲明與實際的數(shù)據(jù)編解碼行為是同一份模型配置驅動的兩面同一組model_config既決定運行時如何解碼/編碼字節(jié)也決定 OpenAPI 文檔如何向調用方描述字段格式。小結與適用邊界優(yōu)先用文件上傳二進制用請求文件、下發(fā)二進制用FileResponseJSON 無法承載原始字節(jié)base64 是可嵌入 JSON 的通用編碼但字符膨脹使其通常不如直接傳文件高效輸入方向用model_config {val_json_bytes: base64}輸出方向用{ser_json_bytes: base64}兩者可同時配置在同一個模型上配置生效后/docs中的 OpenAPI Schema 會自動帶上contentEncoding: base64聲明調用方包括自動生成的客戶端能據(jù)此正確編碼請求體參考實現(xiàn)示例應用、端到端測試、Schema 生成定制。【免費下載鏈接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production項目地址: https://gitcode.com/GitHub_Trending/fa/fastapi創(chuàng)作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考