FastAPI:如何将正文读取为任何有效的 json?

cae*_*eus 20 json pydantic fastapi

抱歉,不精通Python。

我还没有找到该用例的文档。我如何获取请求正文,确保它是一个有效的 Json(任何有效的 json,包括数字、字符串、布尔值和空值,而不仅仅是对象和数组)并获取实际的 Json。使用 pydantic 强制 Json 具有特定的结构。

Yag*_*nci 34

您几乎可以找到Request对象内的所有内容

您可以使用 获取请求正文request.json(),这将为您提供已解析的 JSON 作为字典。

from fastapi import Request, FastAPI

@app.post("/dummypath")
async def get_body(request: Request):
    return await request.json()
Run Code Online (Sandbox Code Playgroud)

如果您想以字符串形式访问正文,则可以使用 request.body()

  • 我使用在正文中选择的表单数据发出请求,并收到此错误“ValueError: [TypeError("'coroutine' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')]” (5认同)
  • @parashuram 使用 Body(...) 的另一个高度投票的答案为我解决了这个问题 (2认同)

JPG*_*JPG 13

如果您确信传入的数据是“有效的 JSON”,则可以创建一个简单的类型注释结构来接收任意 JSON 数据。

from 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}
Run Code Online (Sandbox Code Playgroud)

例子

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\"}"
Run Code Online (Sandbox Code Playgroud)

回复:

{
  "received_data": {
    "test_key": "test_val"
  }
}
Run Code Online (Sandbox Code Playgroud)

2. JSON 数组

curl -X POST "http://0.0.0.0:6022/" -H  "accept: application/json" -H  "Content-Type: application/json" -d "[\"foo\",\"bar\"]"
Run Code Online (Sandbox Code Playgroud)

回复:

{
  "received_data": [
    "foo",
    "bar"
  ]
}
Run Code Online (Sandbox Code Playgroud)

如果您不确定传入数据的内容类型,最好解析请求正文

它可以这样做,

from fastapi import FastAPI, Request

app = FastAPI()


@app.post("/")
async def root(request: Request):
    return {"received_request_body": await request.body()}
Run Code Online (Sandbox Code Playgroud)

这种方法的优点是主体将包含任何类型的数据,JSON、表单数据、多部分表单数据等。

  • 实际上,我想要任何有效的 JSON。包括数字、布尔值、null 和字符串。不仅仅是对象和数组。 (3认同)
  • 这是不对的,如果它不是有效的 JSON,Pydantic 会抛出错误。除此之外,没有所谓的“JSON数组”Python将JSON解析为字典,所以OP的问题非常清楚,他想要获取未解析的实际JSON,并且获取实际JSON的唯一方法是从`request .body()`。 (2认同)

Ole*_*nko 10

接受的答案也是有效的,但 FastAPI 提供了一种内置的方法来做到这一点 - 检查文档正文部分中的奇异值

具有默认值的参数Body获取与传递的 Pydantic 类型参数(在我们的示例中为整个有效负载)不匹配的所有有效负载,并将其转换为 dict。如果 JSON 无效,则会产生标准验证错误。

from fastapi import Body, FastAPI

app = FastAPI()


@app.post('/test')
async def update_item(
        payload: dict = Body(...)
):
    return payload
Run Code Online (Sandbox Code Playgroud)

  • 无可否认,这是正确的方法,并且应该是公认的答案。 (4认同)
  • `dict = Body()` 获胜。这句简单的台词让我困惑了太久。 (3认同)