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

FastAPI: how to read body as any valid json?

抱歉,不精通Python。

我没有找到该用例的文档。如何获取请求正文,确保它是有效的 Json(任何有效的 json,包括数字、字符串、布尔值和空值,而不仅仅是对象和数组) 并得到实际的 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()

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

from fastapi import FastAPI
<b>from typing import Any, Dict, AnyStr, List, Union</b>

app = FastAPI()

<b>JSONObject = Dict[AnyStr, Any]
JSONArray = List[Any]
JSONStructure = Union[JSONArray, JSONObject]</b>


@app.post("/")
async def root(<b>arbitrary_json: JSONStructure = None</b>):
    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, <b>Request</b>

app = FastAPI()


@app.post("/")
async def root(<b>request: Request</b>):
    return {"received_request_body": <b>await request.body()</b>}

这种方法的优点是正文将包含任何类型的数据,JSON、form-data、multipart-form-data 等

文档中已接受的 is valid as well, but FastAPI provides a built-in way to do that - check the Singular values in body 部分。

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

from fastapi import Body, FastAPI

app = FastAPI()


@app.post('/test')
async def update_item(
        payload: dict = Body(...)
):
    return payload

UPD: 关于 ...(省略号)的注释 - 它允许根据需要标记一个值。在 the Required with Ellipsis docs section

中阅读更多内容
from fastapi import Request

async def synonyms__select(request: Request):
    return await request.json()

将return一个JSON对象。

这是一个打印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"}