Skip to content

Commit 869d375

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 53d2453 commit 869d375

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 decimal import Decimal
55
from enum import Enum
66
from ipaddress import (
@@ -94,20 +94,6 @@ def decimal_encoder(dec_value: Decimal) -> Union[int, float]:
9494
}
9595

9696

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

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

0 commit comments

Comments
 (0)