如何使用Python请求将包含unicode字符的JSON数据发布到FastAPI?

问题描述 投票:0回答:2

当 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 解码错误。

python python-requests fastapi pydantic
2个回答
4
投票

这不是Pydantic和FastAPI的问题。您应该对请求数据进行编码,如下所示:

r = requests.post(
    f"http://127.0.0.1:8000/example", data=ex1.model_dump_json().encode('utf-8')
)
print(r.text)
r = requests.post(
    f"http://127.0.0.1:8000/example", data=ex2.model_dump_json().encode('utf-8')
)
print(r.text)
r = requests.post(
    f"http://127.0.0.1:8000/example", data=ex3.model_dump_json().encode('utf-8')
)
print(r.text)


2
投票

从 Python

requests
发送 JSON 数据时,应使用
json
参数来传递有效的字典。使用该参数会将请求的
Content-Type
标头设置为
application/json
。另一方面,
data
参数在发送表单数据时使用,这些数据使用
application/x-www-form-urlencoded
(即
Content-Type
中的默认
requests
)或
multipart/form-data
(如果
files
)进行编码也包含在请求中)。

请查看这个答案这个答案。您可能会发现这个答案,以及这个答案这个答案也很有帮助。

除了将

Content-Type
标头设置为
application/json
之外,您还应该使用 Pydantic 的
model_dump()
方法(有关更多详细信息,请参阅 这个答案),而不是
model_dump_json()
,这会将模型转换为字典。

示例

from pydantic import BaseModel, Field
import requests

class Example(BaseModel):
    id: int = Field(example=1)
    text: str = Field(example="test")


ex1 = Example(id=1, text="Working")
ex2 = Example(id=2, text="this’ will also work")
ex3 = Example(id=3, text="🤗 <- will also work")


url = 'http://127.0.0.1:8000/example'
r = requests.post(url, json=ex1.model_dump())
print(r.text)
r = requests.post(url, json=ex2.model_dump())
print(r.text)
r = requests.post(url, json=ex3.model_dump())
print(r.text)
© www.soinside.com 2019 - 2024. All rights reserved.