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

如何在FastAPI中正确返回JSON格式数据?解决与Flask格式差异

FastAPI与Flask返回JSON格式差异问题解决

问题根源

Flask和FastAPI的响应处理机制存在本质差异:

  • Flask会自动识别返回的dict/list,调用jsonify将其序列化为标准JSON响应;即便返回的是json.dumps生成的字符串,Flask也会将其识别为JSON内容直接返回。
  • FastAPI基于Pydantic/Starlette实现,若返回的是Python原生数据结构(dict/list),会自动用内置编码器完成序列化;但如果返回的是字符串,会直接将其作为纯文本返回,导致字符串被二次转义(出现嵌套引号、转义符)。

你的代码中手动调用json.dumps()返回JSON字符串而非原生数据结构,这就是FastAPI返回格式异常的核心原因。

解决方案

方案1:返回原生数据结构,自定义JSON编码器处理日期类型

去掉json.dumps()调用,直接返回list/dict,同时给FastAPI配置自定义编码器处理date类型:

from fastapi import Request, APIRouter
from fastapi.encoders import jsonable_encoder
from datetime import date
from google.cloud import bigquery

router = APIRouter()
bigquery_client = bigquery.Client()

@router.get('/report')
async def report(request: Request):
    source_id = request.query_params.get("source_id")  # 补充source_id获取逻辑
    response = get_user(bigquery_client, source_id)
    # 用自定义编码器处理日期类型,让FastAPI自动完成序列化
    return jsonable_encoder(response, custom_encoder={date: lambda v: v.isoformat()})

def get_user(client, source_id):
    try:
        query = """ SELECT * FROM ....."""
        job_config = bigquery.QueryJobConfig(
            query_parameters=[
                bigquery.ScalarQueryParameter("source_id", "STRING", source_id),
            ]
        )
        query_job = client.query(query, job_config=job_config)
        result = []
        for row in query_job:
            result.append(dict(row))
        # 直接返回Python列表,而非JSON字符串
        return result

    except Exception as e:
        return str(e)

方案2:转换Row为Dict时直接处理日期字段

如果不想配置全局编码器,可以在将BigQuery返回的Row转为字典时,主动把date类型转成字符串:

from datetime import date
from google.cloud import bigquery
from fastapi import Request, APIRouter

router = APIRouter()
bigquery_client = bigquery.Client()

@router.get('/report')
async def report(request: Request):
    source_id = request.query_params.get("source_id")
    response = get_user(bigquery_client, source_id)
    return response

def get_user(client, source_id):
    try:
        query = """ SELECT * FROM ....."""
        job_config = bigquery.QueryJobConfig(
            query_parameters=[
                bigquery.ScalarQueryParameter("source_id", "STRING", source_id),
            ]
        )
        query_job = client.query(query, job_config=job_config)
        result = []
        for row in query_job:
            row_dict = dict(row)
            # 遍历字典,将日期类型转为ISO格式字符串
            for key, value in row_dict.items():
                if isinstance(value, date):
                    row_dict[key] = value.isoformat()
            result.append(row_dict)
        return result

    except Exception as e:
        return str(e)

效果验证

修改后,FastAPI会返回和Flask完全一致的标准JSON结构,不再出现转义后的字符串格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 13:20:27