mirror of https://github.com/tiangolo/fastapi.git
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).
This commit is contained in:
parent
6bc29cc5ba
commit
6890d46b1d
|
|
@ -1,6 +1,6 @@
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import datetime
|
import datetime
|
||||||
from collections import defaultdict, deque
|
from collections import deque
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from ipaddress import (
|
from ipaddress import (
|
||||||
|
|
@ -14,7 +14,7 @@ from ipaddress import (
|
||||||
from pathlib import Path, PurePath
|
from pathlib import Path, PurePath
|
||||||
from re import Pattern
|
from re import Pattern
|
||||||
from types import GeneratorType
|
from types import GeneratorType
|
||||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union
|
from typing import Any, Callable, Dict, List, Optional, Type, Union
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from fastapi.types import IncEx
|
from fastapi.types import IncEx
|
||||||
|
|
@ -85,20 +85,6 @@ ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def generate_encoders_by_class_tuples(
|
|
||||||
type_encoder_map: Dict[Any, Callable[[Any], Any]],
|
|
||||||
) -> Dict[Callable[[Any], Any], Tuple[Any, ...]]:
|
|
||||||
encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict(
|
|
||||||
tuple
|
|
||||||
)
|
|
||||||
for type_, encoder in type_encoder_map.items():
|
|
||||||
encoders_by_class_tuples[encoder] += (type_,)
|
|
||||||
return encoders_by_class_tuples
|
|
||||||
|
|
||||||
|
|
||||||
encoders_by_class_tuples = generate_encoders_by_class_tuples(ENCODERS_BY_TYPE)
|
|
||||||
|
|
||||||
|
|
||||||
def jsonable_encoder(
|
def jsonable_encoder(
|
||||||
obj: Annotated[
|
obj: Annotated[
|
||||||
Any,
|
Any,
|
||||||
|
|
@ -314,11 +300,9 @@ def jsonable_encoder(
|
||||||
)
|
)
|
||||||
return encoded_list
|
return encoded_list
|
||||||
|
|
||||||
if type(obj) in ENCODERS_BY_TYPE:
|
for base in obj.__class__.__mro__[:-1]:
|
||||||
return ENCODERS_BY_TYPE[type(obj)](obj)
|
if base in ENCODERS_BY_TYPE:
|
||||||
for encoder, classes_tuple in encoders_by_class_tuples.items():
|
return ENCODERS_BY_TYPE[base](obj)
|
||||||
if isinstance(obj, classes_tuple):
|
|
||||||
return encoder(obj)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = dict(obj)
|
data = dict(obj)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue