You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
2.7 KiB

from enum import Enum
from types import GeneratorType
from typing import Any, Set
from pydantic import BaseModel
from pydantic.json import pydantic_encoder
def jsonable_encoder(
obj: Any,
include: Set[str] = None,
exclude: Set[str] = set(),
by_alias: bool = False,
include_none: bool = True,
root_encoder: bool = True,
) -> Any:
errors = []
try:
return known_data_encoder(
obj,
include=include,
exclude=exclude,
by_alias=by_alias,
include_none=include_none,
)
except Exception as e:
if not root_encoder:
raise e
errors.append(e)
try:
data = dict(obj)
return jsonable_encoder(
data,
include=include,
exclude=exclude,
by_alias=by_alias,
include_none=include_none,
root_encoder=False,
)
except Exception as e:
if not root_encoder:
raise e
errors.append(e)
try:
data = vars(obj)
return jsonable_encoder(
data,
include=include,
exclude=exclude,
by_alias=by_alias,
include_none=include_none,
root_encoder=False,
)
except Exception as e:
if not root_encoder:
raise e
errors.append(e)
raise ValueError(errors)
def known_data_encoder(
obj: Any,
include: Set[str] = None,
exclude: Set[str] = set(),
by_alias: bool = False,
include_none: bool = True,
) -> Any:
if isinstance(obj, BaseModel):
return jsonable_encoder(
obj.dict(include=include, exclude=exclude, by_alias=by_alias),
include_none=include_none,
root_encoder=False,
)
if isinstance(obj, Enum):
return obj.value
if isinstance(obj, (str, int, float, type(None))):
return obj
if isinstance(obj, dict):
return {
jsonable_encoder(
key, by_alias=by_alias, include_none=include_none, root_encoder=False
): jsonable_encoder(
value, by_alias=by_alias, include_none=include_none, root_encoder=False
)
for key, value in obj.items()
if value is not None or include_none
}
if isinstance(obj, (list, set, frozenset, GeneratorType, tuple)):
return [
jsonable_encoder(
item,
include=include,
exclude=exclude,
by_alias=by_alias,
include_none=include_none,
root_encoder=False,
)
for item in obj
]
return pydantic_encoder(obj)