介绍
FastAPI 默认就返回 JSON,内部基于 JSONResponse,自动做序列化、设置响应头 Content-Type: application/json。下面分常用写法、自定义响应、序列化规则、异常返回、底层原理。
1. 直接返回 dict
直接返回字典,FastAPI 自动转 JSON。
例子
显示一条记录的详细信息,如:查看某个学生的信息
from fastapi import FastAPI
app = FastAPI()
@app.get("/student")
def get_student():
# 直接返回python字典,框架自动转为json
return {
"code": 200,
"msg": "success",
"data": {
"name": "张三",
"age": 20
}
}
响应结果:
{
"code": 200,
"msg": "success",
"data": {
"name": "张三",
"age": 20
}
}
2. 返回模型(推荐但不常用)
这种用法,官方推荐,但开发中,习惯返回 dict 类型,而 不是返回 模型对象
例子1
直接返回模型对象,功能与返回 dict 类似,用于显示一条记录的详细信息,如:显示用户的信息
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class UserResponse(BaseModel):
id: int
name: str
password: str
@app.get("/user")
def get_user():
user = UserResponse(id=1, name="李四",password="123456")
return user # 返回模型对象,自动序列化为json
响应结果:
{
"id": 1,
"name": "李四",
"password": "123456"
}
缺点
将密码也返回给前端了,这是不合理的,会泄露密码
解决
移除模型的 password 字段
例子2:返回模型对象,过滤敏感字段
定义模型,不包含 password:
class UserResponse(BaseModel):
id: int
name: str
返回模型对象,既使在对象里 加上 password,也不会返回:
@app.get("/user")
def get_user():
# 创建对象时传入 password
user = UserResponse(id=1, name="李四",password="123456")
return user # 返回模型对象,自动序列化为json
执行结果,不包含 password:
{
"id": 1,
"name": "李四"
}
缺点
一般开发中,习惯返回 dict 类型,而 不是返回 模型对象
解决
在装饰器中设置 response_model
3. 设置 response_model,返回dict(推荐且常用)
在装饰器中设置 response_model,返回 dict 类型
这种用法,即符合官方推荐,又符合开发习惯
好处:
- 校验 JSON 返回数据,有缺失报错
- 过滤敏感字段
例子1
校验 JSON 返回数据,有缺失报错
定义模型
class UserResponse(BaseModel):
id: int
name: str
password: str
实现视图函数
- 装饰器需要 指定响应模型
response_model - 视图函数返回
dict
@app.get("/user",response_model=UserResponse)
def get_user():
return {
"id":1,
"name":"李四",
"password":"123456"
}
执行结果:
{
"id": 1,
"name": "李四",
"password":"123456"
}
例子2:有缺失报错
返回的数据缺少 password,与 UserResponse 模型字段不匹配,直接报错
@app.get("/user",response_model=UserResponse)
def get_user():
return {
"id":1,
"name":"李四"
}
执行报错
例子3:过滤敏感字段
很多场景:数据库模型字段很多,不想全部返回给前端,用 response_model 做输出过滤。
注意:返回 dict 中包含 password,通过设置 response_model,会过滤掉 password
定义模型
不包含 password:
class UserResponse(BaseModel):
id: int
name: str
实现视图函数
- 装饰器需要 指定响应模型
response_model - 视图函数返回
dict,既使 加上password,也不会返回
@app.get("/user",response_model=UserResponse)
def get_user():
return {
"id":1,
"name":"李四",
"password":"123456"
}
执行结果,不包含 password:
{
"id": 1,
"name": "李四"
}
4. 不输出未赋值的字段
还可以用 response_model_exclude_unset=True:不输出未赋值的字段。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class UserResponse(BaseModel):
id: int
# 要设置允许None,否则不设置值会报错
name: str | None = None
age: int | None = None
# 返回dict
@app.get("/user",response_model=UserResponse,response_model_exclude_unset=True)
def get_user():
return {
"id":1
}
响应结果:
{
"id": 1
}
5. 统一返回格式
前后端约定统一格式:{code,msg,data},两种实现方式。
方式1:每个接口手动包一层dict(简单小项目)
@app.get("/info")
def info():
return {
"code":200,
"msg":"ok",
"data":{
"name":"李雷",
"age":18,
}
}
方式2:封装工具函数(大项目)
手动构造 JSONResponse,可以自定义 状态码、自定义响应头、直接传入 JSON 字符串
from fastapi.responses import JSONResponse
def resp_ok(data=None,msg="success"):
return JSONResponse({
"code":200,
"msg":msg,
"data":data
})
def resp_fail(code=400,msg="fail",data=None):
return JSONResponse({
"code":code,
"msg":msg,
"data":data
})
@app.get("/test")
def test():
return resp_ok(data={"name":"test"})
底层流程
- 视图函数 return 对象(dict/pydantic/list)
- 调用
jsonable_encoder():把ORM、Pydantic、datetime转成可序列化的python基础类型 - 内部构建
JSONResponse对象 - 调用
json.dumps()序列化为字节流 - 设置响应头
Content‑Type: application/json返回浏览器
注意:如果返回的本身就是 Response(如JSONResponse、HTMLResponse),不会经过jsonable_encoder,直接输出。