【问题标题】:FastAPI: how to read body as any valid json?FastAPI:如何将正文读取为任何有效的 json?
【发布时间】:2021-01-30 09:09:22
【问题描述】:

抱歉,不精通 Python。

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

【问题讨论】:

    标签: json fastapi pydantic


    【解决方案1】:

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

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

    from fastapi import Request, FastAPI
    
    @app.post("/dummypath")
    async def get_body(request: Request):
        return await request.json()
    

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

    【讨论】:

    • 在这个答案的edit 历史中,request.body() 似乎只在代码块内被request.json() 取代:-)
    • 邮递员如何向这个 api 提出请求?
    • 我在正文中选择了表单数据并收到此错误“ValueError: [TypeError("'coroutine' object is not iterable"), TypeError('vars() argument must have dict 属性')]"
    • 解析的 JSON 可以是多种不同的类型,而不仅仅是字典。
    【解决方案2】:

    如果您确信传入的数据是“有效的 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}

    示例

    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()}

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

    【讨论】:

    • 这是不对的,如果不是有效的 JSON,Pydantic 会抛出错误。除此之外,没有什么叫做“JSON 数组” Python 将 JSON 解析为 Dictionary,所以 OP 的问题很明确,他想获得未解析的实际 JSON,只有从 @987654328 获取实际 JSON 的方法@.
    • @YagizcanDegirmenci 是的,有一个叫做JSON Array 的东西不能被解析成 Python dict,而是一个 Python 列表
    • 是的,我很确定 OP 并不是指问题中的 JSON 数组。
    • OP 也没有提到 JSON 对象。这个答案适用于那些想要从请求不是字符串中获取任意JSON(数组或对象)的人,因为我已经提到了
    • 实际上,我想要任何有效的 JSON。包括数字、布尔值、空值和字符串。不仅是对象和数组。
    【解决方案3】:

    接受的 answer 也是有效的,但 FastAPI 提供了一种内置方式来执行此操作 - 请查看文档中的 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
    

    【讨论】:

      【解决方案4】:
      from fastapi import Request
      
      async def synonyms__select(request: Request):
          return await request.json()
      

      将返回一个 JSON 对象。

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-07-05
          • 1970-01-01
          • 2023-01-31
          • 1970-01-01
          • 1970-01-01
          • 2019-08-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多