1

I am trying to figure out how to update my FastAPI app after from Pydantic v1 to Pydantic v2.

Before I had code that worked perfectly fine:


class ObjectId(bson.ObjectId):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, value):
        if isinstance(value, str):
            try:
                return bson.ObjectId(value)
            except bson.errors.InvalidId:
                raise ValueError("Invalid ObjectId")
        elif isinstance(value, bson.ObjectId):
            return value
        else:
            raise TypeError("ObjectId required")


app = FastAPI()

@app.get("/test")
def test(id: ObjectId) -> bool:
    return True

However, when I try to migrate to FastAPI V2:

import bson
from typing import Annotated

from pydantic import (
    field_validator,
    PlainSerializer,
    WithJsonSchema,
    BeforeValidator,
    TypeAdapter,
)
from fastapi import FastAPI


ObjectId = Annotated[
    bson.ObjectId,
    BeforeValidator(lambda x: bson.ObjectId(x) if isinstance(x, str) else x),
    PlainSerializer(lambda x: f"{x}", return_type=str),
    WithJsonSchema({"type": "string"}, mode="validation"),
    WithJsonSchema({"type": "string"}, mode="serialization"),
]

# Casting from str to ObjectId - WORKS
ta = TypeAdapter(
    ObjectId,
    config=dict(arbitrary_types_allowed=True),
)
ta.validate_python("5f7f9f0c2a0e0b0001d5b3d0")
ta.json_schema()

# Use ObjectId as a query parameter in FastAPI - FAILS:
app = FastAPI()

@app.get("/test")
def test(id: ObjectId) -> bool:
    return True

I get the following error message:

fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that <class 'bson.objectid.ObjectId'> is a valid Pydantic field type. If you are using a return type annotation that is not a valid Pydantic field (e.g. Union[Response, dict, None]) you can disable generating the response model from the type annotation with the path operation decorator parameter response_model=None. Read more: https://fastapi.tiangolo.com/tutorial/response-model/

I am a bit confused, because it seems that the problem is not with a response model (which is bool in the example), but with a custom type in query parameter.

I also checked other suggested approaches, for example:

There, it is suggested an alternative approach to introduce a custom annotation type, however, it still does not work for me.

I also did not find any relevant in the FastAPI documentation about query parameters and a list of Extra Data Types.

I would highly appreciate if you could help to find a possible solution.

desa
  • 1,240
  • 12
  • 31

0 Answers0