一个状态码为
422
(
不可处理的实体
)的响应将包含一个响应体,其中指定了错误消息,告诉您的请求中缺少或不符合预期格式的部分。您提供的代码片段显示您正在尝试将
JSON
数据发布到一个期望
user
作为
query
参数而不是
JSON
负载的端点。因此,出现了
422不可处理的实体
错误。下面给出了四种不同的选项,用于定义一个期望
JSON
数据的端点。
选项1
根据
文档,当您需要从客户端(比如浏览器)向API发送
JSON
数据时,您将其作为
请求体(通过
POST
请求)发送。要声明请求体,您可以使用
Pydantic模型。
from pydantic import BaseModel
class User(BaseModel):
user: str
@app.post('/')
def main(user: User):
return user
选项2
如果不想使用Pydantic模型,也可以使用Body参数。如果只使用一个body参数(例如您的示例),可以使用特殊的Body参数embed。
from fastapi import Body
@app.post('/')
def main(user: str = Body(..., embed=True)):
return {'user': user}
选项3
另一种(不太推荐的)方法是使用Dict
类型(或在Python 3.9+中简单地使用dict
)来声明key:value
对。然而,通过这种方式,您无法像Pydantic模型或Body
字段那样对预期的JSON
中的各个属性使用自定义验证(例如,检查电子邮件地址是否有效,或者字符串是否遵循特定的模式)。
from typing import Dict, Any
@app.post('/')
def main(payload: Dict[Any, Any]):
return payload
选项4
如果您确信传入的数据是有效的JSON
,您可以直接使用Starlette的Request
对象来解析请求体作为JSON
,使用await request.json()
。然而,使用这种方法不仅无法对属性进行自定义验证,还需要使用async def
来定义您的端点,因为request.json()
是一个async
方法,因此需要使用await
(请参阅此答案以获取有关def
与async def
的更多详细信息)。
from fastapi import Request
@app.post('/')
async def main(request: Request):
return await request.json()
如果你希望的话,在尝试解析数据之前,你也可以对请求头中的
Content-Type
值进行一些检查,类似于
this answer。然而,仅仅因为一个请求在
Content-Type
头中声明为
application/json
并不总是意味着这是真实的,或者传入的数据是有效的
JSON
(例如,可能缺少花括号、键没有对应的值等)。因此,当你尝试解析数据时,你可以使用
try-except
块来处理任何
JSONDecodeError
,以防你的
JSON
数据格式有问题。
from fastapi import Request
@app.post('/')
async def main(request: Request):
content_type = request.headers.get('Content-Type')
if content_type is None:
return 'No Content-Type provided.'
elif content_type == 'application/json':
try:
json = await request.json()
return json
except JSONDecodeError:
return 'Invalid JSON data.'
else:
return 'Content-Type not supported.'
测试上述选项
使用Python的requests库
相关答案可以在这里找到。
import requests
url = 'http://127.0.0.1:8000/'
payload ={'user': 'foo'}
resp = requests.post(url=url, json=payload)
print(resp.json())
相关答案也可以在这里和这里找到。关于使用axios
的示例,请参考此答案,以及此答案和此答案。
fetch('/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({'user': 'foo'})
})
.then(resp => resp.json())
.then(data => {
console.log(data);
})
.catch(error => {
console.error(error);
});