背景
- 創建 FastAPI 路徑操作函數時,通常可以從中返回任何數據:字典、列表、Pydantic 模型、數據庫模型等
- 默認情況下,FastAPI 會使用 jsonable_encoder 自動將該返回值轉換為 JSON 字符串
- 然后,FastAPI 會將與 JSON 兼容的數據(例如 dict)放在 JSONResponse 中,然后將 JSONResponse 返回給客戶端
- 總結:默認情況下,FastAPI 將使用 JSONResponse 返回響應
- 但是可以直接從路徑操作函數中返回自定義的 JSONResponse
返回響應數據的常見方式(基礎版)
https://www.cnblogs.com/poloyy/p/15364635.html
最簡單的栗子
路徑操作函數返回一個 Pydantic Model
#!usr/bin/env python # -*- coding:utf-8 _*- """ # author: 小菠蘿測試筆記 # blog: https://www.cnblogs.com/poloyy/ # time: 2021/10/3 3:26 下午 # file: 38_responses.py """ from typing import Optional import uvicorn from fastapi import FastAPI from fastapi.encoders import jsonable_encoder from fastapi.responses import JSONResponse from pydantic import BaseModel app = FastAPI() class Item(BaseModel): id: str name: str title: Optional[str] = None @app.post("/item") async def get_item(item: Item): # 打印看看傳進來的數據是什么 print(item, type(item)) # 直接返回傳進來的數據 return item if __name__ == '__main__': uvicorn.run(app="38_responses:app", reload=True, host="127.0.0.1", port=8080)
正常傳參的請求結果
Response Header 的顯示 content-type 是 JSON
console 打印結果
id='string' name='string' title='string' <class '38_responses.Item'> INFO: 127.0.0.1:51856 - "POST /item HTTP/1.1" 200 OK
- item 類型的確是 Pydantic Model 類
- 但最終返回給客戶端的是一個 JSON 數據
等價寫法
@app.post("/item") async def get_item(item: Item): return item
這樣寫也能返回 JSON 數據,是因為FastAPI 是自動幫忙做了轉換的
等價寫法如下
from fastapi.encoders import jsonable_encoder @app.post("/item") async def get_item(item: Item): json_body = jsonable_encoder(item) return JSONResponse(content=json_body)
打印數據,來看看細節
@app.post("/item2") async def get_item(item: Item): json_body = jsonable_encoder(item) print(json_body, type(json_body)) return JSONResponse(content=json_body)
console 打印結果
{'id': 'string', 'name': 'string', 'title': 'string'} <class 'dict'> INFO: 127.0.0.1:52880 - "POST /item2 HTTP/1.1" 200 OK
假設將 item Pydantic Model 類型直接傳給 JSONResponse 呢?
@app.post("/item3") async def get_item(item: Item): return JSONResponse(content=item)
訪問該接口就會報錯
raise TypeError(f'Object of type {o.__class__.__name__} ' TypeError: Object of type Item is not JSON serializable
- 類型錯誤:項目類型的對象不是 JSON 可序列化的
- 因為它無法轉換為 JSON 數據,所以報錯了
看看 JSONResponse 源碼
會調用 json.dumps() 方法
看看 Response 源碼
看到其實可以自定義 status_code、headers、media_type 哦
headers 后面再用單獨的篇幅來講
修改 status_code 響應碼
@app.post("/item2") async def get_item(item: Item): json_item = jsonable_encoder(item) return JSONResponse(content=json_item, status_code=status.HTTP_201_CREATED)
正確傳參的請求結果
更多自定義響應類型
- JSONResponse
- HTMLResponse、PlainTextResponse
- ORJSONResponse、UJSONResponse
- RedirectResponse
- StreamingResponse、FileResponse