将 pathlib.Path 数据发送到 FastAPI:PosixPath 不可 JSON 序列化

Cod*_*Cat 5 python json pydantic fastapi

我已经使用 FastAPI 构建了一个 API,并尝试从客户端向它发送数据。

API 和客户端都使用类似的 Pydantic 模型来处理我要提交的数据。这包括一个包含文件路径的字段,我将其存储在 pathlib.path 类型的字段中。

然而,FastAPI 不接受提交,因为它显然无法处理路径对象:

TypeError: Object of type PosixPath is not JSON serializable

这是显示问题的最小测试文件:

import pathlib
from pydantic import BaseModel
from fastapi import FastAPI
from fastapi.testclient import TestClient


api = FastAPI()
client = TestClient(api)

class Submission(BaseModel):
    file_path: pathlib.Path

@api.post("/", response_model=Submission)
async def add_submission(subm: Submission):
    print(subm)
    # add submission to database
    return subm


def test_add_submission():
    data = {"file_path": "/my/path/to/file.csv"}
    print("original data:", data)

    # create a Submission object, which casts filePath to pathlib.Path:
    submission = Submission(**data)  
    print("submission object:", submission)

    payload = submission.dict()
    print("payload:", payload)

    response = client.post("/", json=payload)  # this throws the error
    assert response.ok

test_add_submission()
Run Code Online (Sandbox Code Playgroud)

当我更改客户端的模型以使用字符串而不是 Path for 时file_path,事情就会顺利进行。但是,当创建提交对象时,我失去了将输入转换为路径的神秘力量,然后拥有具有所有可能性的路径属性。当然,一定有更好的方法吗?

将 pathlib.PosixPath 对象作为有效负载的一部分发送到 FastAPI API 的正确方法是什么?

(这是 Ubuntu 上的 Python 3.8.9、fastapi 0.68.1、pydantic 1.8.2)

fin*_*mer 3

您代码的问题是,您首先将 pydantic 模型转换为字典,然后将其传递给客户端,客户端使用自己的 json 序列化器,而不是 pydantic 提供的序列化器。

submission.dict()将任何 pydantic 模型转换为字典,但保留任何其他数据类型。

使用client.post("/", json=payload) requestsjson 序列化器,它无法处理pathlib.Path.

解决办法是,不先将pydantic模型转换成dict,而是使用json()pydantic模型本身的方法,传递给客户端。

response = client.post("/", data=submission.json())
Run Code Online (Sandbox Code Playgroud)

请注意,您必须将参数更改jsondata