当 FastAPI 端点需要 Pydantic 模型并且通过字符串传递模型时,它会按预期工作,除非该字符串包含 unicode 字符。
首先,我使用示例模型为 FastAPI 创建一个示例应用程序。
serv.py
from pydantic import BaseModel
class exClass(BaseModel):
id: int = Field(example=1)
text: str = Field(example="Text example")
app = FastAPI(debug=True)
@app.post("/example")
async def receive_pyd(ex: exClass):
print(ex)
return True
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
显示相关错误的客户端
client.py
from pydantic import BaseModel, Field
import requests
class exClass(BaseModel):
id: int = Field(example=1)
text: str = Field(example="Text example")
ex1 = exClass(id=1, text="working example")
ex2 = exClass(id=2, text="this’ will fail")
ex3 = exClass(id=3, text="🤗 <- also non-working")
r = requests.post(f"http://127.0.0.1:8000/example", data=ex1.model_dump_json())
print(r.text)
r = requests.post(f"http://127.0.0.1:8000/example", data=ex2.model_dump_json())
print(r.text)
r = requests.post(f"http://127.0.0.1:8000/example", data=ex3.model_dump_json())
print(r.text)
输出:
true
Invalid HTTP request received.
Invalid HTTP request received.
当
text
包含 unicode 字符时,结果是 422 Unprocessable Entity。我尝试过 ex.dict()、model_dump(),并在请求调用中使用 json 而不是数据。在 FastAPI/starlette 中启用调试会冒出无效的 HTTP 请求是 JSON 解码错误。
这不是Pydantic和FastAPI的问题。您应该对请求数据进行编码并设置标头,如下所示:
r = requests.post(
f"http://127.0.0.1:8000/example", data=ex1.model_dump_json().encode('utf-8'),
headers={'Content-type': 'application/json; charset=utf-8'}
)
print(r.text)
r = requests.post(
f"http://127.0.0.1:8000/example", data=ex2.model_dump_json().encode('utf-8'),
headers={'Content-type': 'application/json; charset=utf-8'}
)
print(r.text)
r = requests.post(
f"http://127.0.0.1:8000/example", data=ex3.model_dump_json().encode('utf-8'),
headers={'Content-type': 'application/json; charset=utf-8'}
)
print(r.text)