【问题标题】:RequestValidationError: JSON object must be str, bytes or bytearray (type=type_error.json)RequestValidationError:JSON 对象必须是 str、bytes 或 bytearray (type=type_error.json)
【发布时间】:2022-12-08 08:14:40
【问题描述】:

我的 FastAPI 应用程序中有一个端点用于接收表单数据:

@router.post("/foobar")
async def handler(
    form_data: Bar = Depends(Bar.as_form),
) -> JSONResponse:
    ...

我想做的是在pydantic 的帮助下验证表单数据。以下是模型:

from fastapi import Form
from pydantic import BaseModel, Json


class Foo(BaseModel):
    a: str


class Bar(BaseModel):
    any_field: Optional[List[Foo]]

    @classmethod
    def as_form(
        cls,
        any_field: Json[List[Foo]] = Form(None, media_type="application/json"),
    ) -> "Bar":
        return cls(any_field=any_field)

但我收到以下错误:

fastapi.exceptions.RequestValidationError: 1 validation error for Request
body -> any_field
  JSON object must be str, bytes or bytearray (type=type_error.json)

我已经为 RequestValidationError 添加了异常处理程序以确保 any_field 实际上是 str 类型:

@application.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    body: FormData = exc.body

    return JSONResponse(
        content={"msg": str([type(v) for v in body.values()])},
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY
    )

这是我的要求:

如您所见,它是str

为什么会出现这个错误?

【问题讨论】:

    标签: python fastapi pydantic


    【解决方案1】:

    您可以让 FastAPI 自己进行验证。例如...

    from fastapi  import FastAPI, Form, File, UploadFile
    from pydantic import BaseModel, Json
    from typing   import Optional, List
    
    class Foo(BaseModel):
        a: str
    
    class Bar(BaseModel):
        any_field: Optional[List[Foo]] = Form()
    
    app = FastAPI()
    
    @app.post("/foobar")
    async def handler(upload: UploadFile = File(), form_data: Json[Bar] = Form()):
        return {'form_data': form_data, 'upload': upload.filename}
    

    这是说明端点使用的代码...

    import requests
    import json
    
    reqUrl = "http://127.0.0.1:8000/foobar"
    
    with open("/Users/pelletier/Playground/scores.csv", "rb") as upload:
        post_files = {'upload': upload}
        payload    = {'form_data': json.dumps({'any_field': [{'a': 'foo'}, {'a': 'foo'}]})}
        response   = requests.post(reqUrl, data=payload, files=post_files)
        print(response.text)
    

    【讨论】:

    • 谢谢您的回答。是的,我知道这一点,但我想发送内容类型为multipart/form-data 的请求。所以,我需要以这种方式验证数据
    • 我更新了答案以说明 multipart/form-data 的处理
    猜你喜欢
    • 2017-07-10
    • 2019-08-27
    • 2021-06-17
    • 1970-01-01
    • 2021-09-09
    • 2021-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多