FastAPI(46)- JSONResponse


背景

  • 創建 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)

 

正確傳參的請求結果

 

更多自定義響應類型

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM