fastapi 如何让单个 endpoint 支持多种响应格式(json/csv)
技术百科
舞姬之光
发布时间:2026-01-17
浏览: 次 FastAPI可通过Accept头内容协商实现JSON/CSV多格式响应:匹配"json"或"csv"子串,JSON直接返回Pydantic模型或dict,CSV则用StreamingResponse配合StringIO生成流式响应并设置对应Content-Type及Content-Disposition头。
FastAPI 本身不直接内置多格式响应(如 JSON/CSV)的自动切换,但可以通过 内容协商(Content Negotiation) —— 即解析请求头中的 Accept 字段,结合手动构造不同响应体来实现。核心思路是:同一个 endpoint 根据客户端期望的格式,返回对应结构的数据(JSON 或 CSV 流),同时设置正确的 Content-Type 和 Content-Disposition(尤其对 CSV 下载有用)。
1. 基于 Accept 头判断格式
读取 request.headers.get("accept"),粗略匹配 application/json 或 text/csv(或通配符 */*)。注意:浏览器通常发 Accept: text/html,application/xhtml+xml...,所以别只依赖精确匹配,可做子串判断或用标准库 email.message.Message 解析更严谨(但多数场景简单判断够用)。
- 推荐写法:检查
"json" in accept.lower()或"csv" in accept.lower() - 若未明确指定,可设默认格式(如 JSON),或按业务定优先级
2. 返回 JSON:直接用 Pydantic 模型或 dict
这是 FastAPI 默认行为。只要函数返回一个可序列化的对象(dict、Pydantic model、list),且未显式设置响应类型,FastAPI 自动转为 JSON 并设 Content-Type: application/json。
- 无需额外操作,保持原样返回即可
- 若需自定义 JSON 响应结构(如加
{"data": ...}包裹),直接 return 字典
3. 返回 CSV:用 StreamingResponse + StringIO
CSV 不适合用普通 JSON 响应,要用 StreamingResponse 流式输出,并设置正确头部:
- 导入:
from fastapi import Response和from starlette.responses import StreamingResponse - 用
io.StringIO构建 CSV 内容,再用StringIO.getvalue().encode("utf-8")转 bytes - 响应 headers 至少包含:
{"Content-Type": "text/csv; charset=utf-8"};若希望浏览器下载,加"Content-Disposition": 'attachment; filename="data.csv"' - 示例片段:
import io
import csv
from starlette.responses import StreamingResponse
def generate_csv(data: list[dict]):
output = io.StringIO()
if data:
writer = csv.DictWriter(output, fieldnames=data[0].keys())
writer.writeheader()
writer.writerows(data)
output.seek(0)
return StreamingResponse(
iter([output.getvalue().encode("utf-8")]),
media_type="text/csv; charset=utf-8",
headers={"Content-Disposition": 'attachment; filename="report.csv"'}
)
4. 完整 endpoint 示例
把以上逻辑组合进一个路由:
- 接收 query 参数(如
format=json)或仅靠Accept头均可;建议两者都支持,更灵活 - 数据源统一获取(比如从 DB 或 mock),再分支处理格式
- 注意:CSV 不支持嵌套结构,需扁平化字段(如把
{"user": {"name": "a"}}展开为{"user_name": "a"})
# ai
# 这是
# 可以通过
# 可通过
# 均可
# 自定义
# 要用
# 浏览器
# app
# 不支持
# 再用
# js
# json
# go
# 路由
# format
# 对象
# html
# 标准库
# stream
# xml
# 流式
# csv
# 来实现
# fastapi
# xhtml
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- windows如何备份注册表_windows导出和
- c++中如何使用虚函数实现多态_c++多态性实现原
- php订单日志权限怎么设_php订单日志文件权限设
- Win11怎么设置默认图片查看器_Windows1
- Drupal 中渲染节点时出现 HTML 标签嵌套
- 如何在Golang中使用container/hea
- 如何使用Golang实现聊天室消息存档_存储聊天记
- Python网页解析流程_html结构说明【指导】
- php条件判断怎么写_ifelse和switchc
- PHP怎么接收URL中的锚点参数_获取#后面参数值
- LINUX如何删除用户和用户组_Linux use
- Win11如何设置ipv6 Win11开启IPv6
- Mac如何开启夜览模式_Mac护眼模式设置与定时
- 如何使用Golang操作指针变量_Golang解引
- Python随机数生成_random模块说明【指导
- Win10怎么查看内存时序参数_Win10CPU-
- Win11怎么关闭自动更新 Win11永久关闭系统
- Python数据挖掘核心算法实践_聚类分类与特征工
- Windows11怎样开启游戏模式_Windows
- Mac怎么设置登录项_Mac管理开机自启动程序【教
- Win11怎么清理C盘系统日志_Win11清理系统
- 如何在 PHP 单元测试中正确模拟带方法的图像处理
- php增删改查在php8里有什么变化_新特性对cu
- 如何使用Golang开发基础文件下载功能_Gola
- 如何使用正则表达式提取以编号开头、后接多个注解的逻
- Win11怎么关闭内容自适应亮度_Windows1
- 如何在Golang中使用encoding/gob序
- 如何有效拦截拼接式恶意域名的垃圾信息
- Win11如何暂停系统更新 Win11暂停更新最长
- php本地部署后数据库连接报错_1045acces
- Windows10系统怎么查看系统版本_Win10
- Windows10电脑怎么设置虚拟光驱_Win10
- Win11怎么设置虚拟桌面 Win11新建多桌面切
- WindowsUSB驱动安装异常怎么办_USB驱动
- 如何使用Golang recover捕获panic
- 如何使用Golang搭建Web开发环境_快速启动H
- Go 中实现 Python urllib.quot
- Win11怎么更改鼠标指针方案_Windows11
- Windows 11怎么设置默认解压软件_Wind
- Mac上的iMovie如何剪辑视频?(新手入门教程
- 如何在Golang中使用replace替换模块_指
- Win11怎么更改系统语言_Win11中文语言包下
- Python深度学习实战教程_神经网络模型构建与训
- Windows10怎么用“讲述人”读屏辅助 Win
- Win11右键反应慢怎么办 Win11优化右键菜单
- Windows10电脑怎么设置自动连接WiFi_W
- Python类装饰器使用_元编程解析【教程】
- 如何使用Golang读取日志文件_Golang b
- php下载安装后memory_limit怎么设置_
- Windows10如何更改计算机工作组_Win10


QQ客服