Skip to content

Commit c2766f1

Browse files
committed
Compare objects MRO with encoders at runtime
The previous implementation doesn't handle subclass instances when pydantic.json.ENCODERS_BY_TYPE is modified after fastapi.encoders import. This diff makes it easier for developers to add custom encoders that also work with subclass instances (and it simplifies the code, as well).
1 parent d06ab3f commit c2766f1

File tree

1 file changed

+4
-20
lines changed

1 file changed

+4
-20
lines changed

fastapi/encoders.py

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import dataclasses
22
import datetime
3-
from collections import defaultdict, deque
3+
from collections import deque
44
from collections.abc import Callable
55
from decimal import Decimal
66
from enum import Enum
@@ -95,20 +95,6 @@ def decimal_encoder(dec_value: Decimal) -> int | float:
9595
}
9696

9797

98-
def generate_encoders_by_class_tuples(
99-
type_encoder_map: dict[Any, Callable[[Any], Any]],
100-
) -> dict[Callable[[Any], Any], tuple[Any, ...]]:
101-
encoders_by_class_tuples: dict[Callable[[Any], Any], tuple[Any, ...]] = defaultdict(
102-
tuple
103-
)
104-
for type_, encoder in type_encoder_map.items():
105-
encoders_by_class_tuples[encoder] += (type_,)
106-
return encoders_by_class_tuples
107-
108-
109-
encoders_by_class_tuples = generate_encoders_by_class_tuples(ENCODERS_BY_TYPE)
110-
111-
11298
def jsonable_encoder(
11399
obj: Annotated[
114100
Any,
@@ -314,11 +300,9 @@ def jsonable_encoder(
314300
)
315301
return encoded_list
316302

317-
if type(obj) in ENCODERS_BY_TYPE:
318-
return ENCODERS_BY_TYPE[type(obj)](obj)
319-
for encoder, classes_tuple in encoders_by_class_tuples.items():
320-
if isinstance(obj, classes_tuple):
321-
return encoder(obj)
303+
for base in obj.__class__.__mro__[:-1]:
304+
if base in ENCODERS_BY_TYPE:
305+
return ENCODERS_BY_TYPE[base](obj)
322306
if is_pydantic_v1_model_instance(obj):
323307
raise PydanticV1NotSupportedError(
324308
"pydantic.v1 models are no longer supported by FastAPI."

0 commit comments

Comments
 (0)