向FastAPI发送pathlib.Path数据时PosixPath不可JSON序列化如何解决
问题原因
报错的根本原因是Python默认的JSON序列化器不支持pathlib.Path类型,你调用submission.dict()得到的字典中,file_path字段仍然是PosixPath对象,直接传给请求的json参数时无法完成序列化。
解决方案
不需要修改模型的file_path字段类型,完全可以保留Pydantic自动转换为Path类型的能力,以下是两种常用实现方式:
方法1:使用FastAPI自带的jsonable_encoder转换payload
jsonable_encoder会自动把所有非JSON原生类型(包括Path、datetime等)转换为可序列化的格式,是FastAPI生态下最推荐的做法。
修改后的测试代码如下:
import pathlib from pydantic import BaseModel from fastapi import FastAPI from fastapi.testclient import TestClient from fastapi.encoders import jsonable_encoder # 新增导入 api = FastAPI() client = TestClient(api) class Submission(BaseModel): file_path: pathlib.Path @api.post("/", response_model=Submission) async def add_submission(subm: Submission): # 这里拿到的subm.file_path仍然是Path类型,可以正常做Path相关操作 print(type(subm.file_path)) # 输出 <class 'pathlib.PosixPath'> return subm def test_add_submission(): data = {"file_path": "/my/path/to/file.csv"} submission = Submission(**data) # 用jsonable_encoder转换模型为可序列化的字典 payload = jsonable_encoder(submission) response = client.post("/", json=payload) assert response.ok # 返回结果也会被Pydantic自动转成Path类型 resp_submission = Submission(**response.json()) print(type(resp_submission.file_path)) # 输出 <class 'pathlib.PosixPath'> test_add_submission()
方法2:直接使用Pydantic模型的json()方法生成JSON字符串
Pydantic模型自带的json()方法已经内置了所有兼容类型的序列化逻辑,Path会自动被转为字符串,直接作为请求体发送即可:
def test_add_submission(): data = {"file_path": "/my/path/to/file.csv"} submission = Submission(**data) # 直接生成JSON字符串作为请求内容 response = client.post( "/", content=submission.json(), headers={"Content-Type": "application/json"} ) assert response.ok
原理说明
两种方案都不会影响两端的类型能力:
- 服务端收到请求后,Pydantic会自动把路径字符串反序列化为
Path对象,接口内可以直接调用所有Path相关方法 - 返回时FastAPI会自动处理
response_model的序列化,把Path对象转为字符串返回,客户端拿到响应后也可以直接用同一个Pydantic模型转换回Path类型使用。
内容的提问来源于stack exchange,提问作者CodingCat
相关产品推荐
相关产品推荐

