You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI中间件包装响应报错,如何正确将原结果作为字典元素返回?

问题

用户编写了如下FastAPI代码,试图通过HTTP中间件将接口的原响应结果作为字典的response元素返回:

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()

@app.middleware("http")
async def response_middleware(request: Request, call_next):
    # 执行请求
    results = await call_next(request)

    return JSONResponse(content={
        'response': results 
    })

  
@app.post("/test/")
async def test_func():
    results = {
        'test': 10
    }

    return results

运行时触发错误:

raise TypeError(f'Object of type {o.__class__.__name__} ' TypeError: Object of type 
_StreamingResponse is not JSON serializable

用户尝试直接返回字典,问题仍未解决:

async def response_middleware(request: Request, call_next):
    # 执行请求
    results = await call_next(request)

    return {
        'response': results 
    }

现需解决两个问题:

  1. 如何正确将原结果作为输出字典元素传递?
  2. 是否必须使用JSONResponse?

解答

错误原因

call_next(request)返回的是响应对象(比如JSONResponse或内部的_StreamingResponse),而非直接的响应内容(字典/JSON数据)。直接把这个对象放进JSONResponse的content里,会因响应对象无法被JSON序列化而报错。

正确实现方式

方法1:读取原响应内容重新封装

先获取原响应的状态码、请求头,再读取并解析响应体内容,最后将其封装到目标字典中返回:

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import json

app = FastAPI()

@app.middleware("http")
async def response_middleware(request: Request, call_next):
    response = await call_next(request)
    
    # 读取原响应体的二进制内容并解析为字典
    body = await response.body()
    original_content = json.loads(body)
    
    # 封装成统一格式的响应,保留原响应的状态码和请求头
    return JSONResponse(
        content={'response': original_content},
        status_code=response.status_code,
        headers=dict(response.headers)
    )

@app.post("/test/")
async def test_func():
    return {'test': 10}

注意:该方法仅适用于原响应为JSON格式的接口,若原响应是HTML、二进制文件等格式,需针对性调整解析逻辑。

方法2:用响应模型替代中间件(更简洁)

如果所有接口都需要统一响应格式,推荐使用FastAPI的响应模型功能,无需中间件:

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

# 定义统一的响应模型
class UnifiedResponse(BaseModel):
    response: dict

@app.post("/test/", response_model=UnifiedResponse)
async def test_func():
    # 直接返回符合模型结构的数据
    return {'response': {'test': 10}}

是否必须使用JSONResponse?

不是必须,但要明确以下几点:

  • 若接口统一返回JSON格式,使用JSONResponse是最规范的做法,FastAPI也会自动将字典转换为JSONResponse。
  • 在中间件中,必须返回响应对象(如JSONResponse、HTMLResponse等),不能直接返回字典——虽然FastAPI会自动将字典转为JSONResponse,但这里你要包裹的是原响应内容,直接返回字典会因原响应对象无法序列化而报错,逻辑也不符合预期。

内容的提问来源于stack exchange,提问作者Zhihar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 12:12:47