我还没有找到针对那个使用案例的文档。 我该如何获取请求主体,确保它是有效的JSON(任何有效的JSON,包括数字,字符串,布尔值和null,不仅限于对象和数组),并获取实际的JSON。 使用Pydantic强制JSON具有特定的结构。
您可以在Request
对象中找到几乎所有的东西。
您可以使用request.json()
获取请求正文,这将以字典形式给您解析后的JSON。
from fastapi import Request, FastAPI
@app.post("/dummypath")
async def get_body(request: Request):
return await request.json()
如果您想将请求的主体作为字符串获取,可以使用 request.body()
。request.body()
被替换为request.json()
:-) - tgogosBody
的参数会获取所有与传递的Pydantic类型参数不匹配的有效负载(在我们的情况下是整个有效负载),并将其转换为适当的Python类型。如果JSON无效,则会产生标准的验证错误。
from typing import Any
from fastapi import Body, FastAPI
app = FastAPI()
@app.post('/test')
async def update_item(
payload: Any = Body(None)
):
return payload
更新:关于第一个Body位置参数(默认值)的说明 - 这里的None表示请求体是可选的,...
(省略号) - 表示它是必需的(不传递任何内容实际上会保持它是必需的)。在带有省略号的必需参数文档部分中了解更多信息。
此外,这个解决方案适用于只包含null
、true
、false
、任意字符串和任意数字的JSON。
dict = Body()
赢了。这个简单的语句让我苦苦追寻了很久。 - zelusprequest.json()
经常与常规的参数类型一起推荐和使用。在我看来,除非你需要处理复杂的请求体,否则Body()
是FastAPI最自然的方式。 - Oleh Rybalchenkonull
、true
、false
、任何字符串、任何数字和数组。 - undefinednull
,true
,false
,任何字符串,任何数字 - 这些单独不能构成有效的JSON,所以它不应该接受它们。 - undefinedfrom fastapi import FastAPI
from typing import Any, Dict, AnyStr, List, Union
app = FastAPI()
JSONObject = Dict[AnyStr, Any]
JSONArray = List[Any]
JSONStructure = Union[JSONArray, JSONObject]
@app.post("/")
async def root(arbitrary_json: JSONStructure = None):
return {"received_data": arbitrary_json}
1. JSON对象
curl -X POST "http://0.0.0.0:6022/" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"test_key\":\"test_val\"}"
响应:
{
"received_data": {
"test_key": "test_val"
}
}
2. JSON数组
curl -X POST "http://0.0.0.0:6022/" -H "accept: application/json" -H "Content-Type: application/json" -d "[\"foo\",\"bar\"]"
响应:
{
"received_data": [
"foo",
"bar"
]
}
如果您不确定传入数据的内容类型,最好解析请求正文。
可以这样做:
from fastapi import FastAPI, Request
app = FastAPI()
@app.post("/")
async def root(request: Request):
return {"received_request_body": await request.body()}
这种方法的优点在于请求主体可以包含任何类型的数据,如JSON、form-data、multipart-form-data等。
request.body()
中获取。 - Yagiz Degirmencifrom fastapi import Request
async def synonyms__select(request: Request):
return await request.json()
将返回一个JSON对象。
async def print_request(request):
print(f'request header : {dict(request.headers.items())}' )
print(f'request query params : {dict(request.query_params.items())}')
try :
print(f'request json : {await request.json()}')
except Exception as err:
# could not parse json
print(f'request body : {await request.body()}')
@app.post("/printREQUEST")
async def create_file(request: Request):
try:
await print_request(request)
return {"status": "OK"}
except Exception as err:
logging.error(f'could not print REQUEST: {err}')
return {"status": "ERR"}
如果你正在使用BaseModel并且想要一个JSON字段,你可以从pydantic导入Json。
from fastapi import FastAPI
from pydantic import BaseModel, Json, Field
app = FastAPI()
class MockEndpoint(BaseModel):
endpoint: str = Field(description="API endpoint to mock")
response: Json = Field(description="Example response of the endpoint")
@app.get("/")
async def root():
return {"message": "Hello World"}
@app.post("/mock")
async def mock_request(mock_endpoint: MockEndpoint):
return mock_endpoint
在某些情况下,您可能需要将数据类型(如Pydantic模型)转换为与JSON兼容的格式。
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel
import simplejson as json
class SubmitGeneral(BaseModel):
controllerIPaddress: str
readerIPaddress: str
ntpServer: str
@app.post("/submitGeneral")
async def submitGeneral(data: SubmitGeneral):
data = jsonable_encoder(data)
#data = json.loads(data.json()) # same as above line
print(f"data = {json.dumps(data)}")
# you have to access the properties with brackets, not by dot notation
query = f"update LocalPLC set ControllerIpAddress = '{data['controllerIPaddress']}', ReaderIPAddress = '{data['readerIPaddress']}'"
return {"status": "OK"}
这也是另一种方法,可以将任何形式的 Json 作为输入
@app.post("/dict/")
async def post_dict(data: Dict[str, Any]):
return data
但我猜这不是做事情最干净的方式