Как изменить ответ при ошибке валидации от pydantic в FastAPI

Есть такая схема:

CONST_DATA = ['a', 'b']
class Sample(BaseModel):
    field1: str
    field2: str

    @validator("field2")
    def validate_fied2(cls, value):

        if value in CONST_DATA:
            return value
        raise PydanticCustomError('value_error', f"fied2 should be in: {CONST_DATA}")

Когда намерено вызываешь ошибку выходит такой ответ:

{
  "error": "Bad request",
  "Not found": "[{'type': 'value_error', 'loc': ('body', 'field2'), 'msg': \"fied2 should be in: ['a', 'b']\", 'input': 'string'}]"
}

Можно ли как-то что-то переопределить, чтобы ошибка выходила вида:

{
  "error": "fied2 should be in: ['a', 'b']",
  "success": false
}

Ответы (2 шт):

Автор решения: NEStenerus nester

Примерно вот так:

from fastapi import FastAPI, Request
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import BaseModel, ValidationError, validator
from pydantic.errors import PydanticTypeError
CONST_DATA = ['a', 'b']

class Sample(BaseModel):
    field1: str
    field2: str

    @validator("field2")
    def validate_field2(cls, value):
        if value in CONST_DATA:
            return value
        raise PydanticTypeError(
            code='value_error',
            msg_template=f'field2 should be in: {CONST_DATA}',
        )


app = FastAPI()


@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: ValidationError):
    errors = exc.errors()
    print(errors)
    for error in errors:
        if error.get('ctx', {}).get('code', '') == 'value_error':
            return JSONResponse(
                status_code=400,
                content={"error": error['msg'], "success": False},
            )
    return JSONResponse(
        status_code=400,
        content={"error": "Invalid input", "success": False},
    )

@app.post("/sample/")
async def create_sample(sample: Sample):
    return sample


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
→ Ссылка
Автор решения: Алексей

Оставлю свой вариант решения (благодаря комментарию @insolor нашел решение) - мне кажется он более лаконичен, чем предоставленный.

from fastapi import  Request

class CustomException(Exception):
    def __init__(self, message: str):
        self.message = message


CONST_DATA = ['a', 'b']
class Sample(BaseModel):
    field1: str
    field2: str

    @validator("field2")
    def validate_fied2(cls, value):

        if value in CONST_DATA:
            return value
        raise CustomException(message=f"field2 should be in: {CONST_DATA}")


@app.exception_handler(CustomException)
async def unicorn_exception_handler(request: Request, exc: CustomException):
    return JSONResponse(
        status_code=418,
        content={"success": False,
                 "error": exc.message},
    )

При вызове ошибки отработает как надо:

{
  "success": false,
  "error": "field2 should be in: ['a', 'b']"
}

Можно, конечно еще накидать еще параметры какие на входе были, но это уже будет громоздко и смысл потеряется

→ Ссылка