# This file was auto-generated by Fern from our API Definition. """ jsonable_encoder converts a Python object to a JSON-friendly dict (e.g. datetimes to strings, Pydantic models to dicts). Taken from FastAPI, and made a bit simpler https://github.com/tiangolo/fastapi/blob/master/fastapi/encoders.py """ import base64 import dataclasses import datetime as dt from enum import Enum from pathlib import PurePath from types import GeneratorType from typing import Any, Callable, Dict, List, Optional, Set, Union import pydantic from .datetime_utils import serialize_datetime from .pydantic_utilities import ( IS_PYDANTIC_V2, encode_by_type, to_jsonable_with_fallback, ) SetIntStr = Set[Union[int, str]] DictIntStrAny = Dict[Union[int, str], Any] def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any], Any]]] = None) -> Any: custom_encoder = custom_encoder or {} if custom_encoder: if type(obj) in custom_encoder: return custom_encoder[type(obj)](obj) else: for encoder_type, encoder_instance in custom_encoder.items(): if isinstance(obj, encoder_type): return encoder_instance(obj) if isinstance(obj, pydantic.BaseModel): if IS_PYDANTIC_V2: encoder = getattr(obj.model_config, "json_encoders", {}) # type: ignore # Pydantic v2 else: encoder = getattr(obj.__config__, "json_encoders", {}) # type: ignore # Pydantic v1 if custom_encoder: encoder.update(custom_encoder) obj_dict = obj.dict(by_alias=True) if "__root__" in obj_dict: obj_dict = obj_dict["__root__"] if "root" in obj_dict: obj_dict = obj_dict["root"] return jsonable_encoder(obj_dict, custom_encoder=encoder) if dataclasses.is_dataclass(obj): obj_dict = dataclasses.asdict(obj) # type: ignore return jsonable_encoder(obj_dict, custom_encoder=custom_encoder) if isinstance(obj, bytes): return base64.b64encode(obj).decode("utf-8") if isinstance(obj, Enum): return obj.value if isinstance(obj, PurePath): return str(obj) if isinstance(obj, (str, int, float, type(None))): return obj if isinstance(obj, dt.datetime): return serialize_datetime(obj) if isinstance(obj, dt.date): return str(obj) if isinstance(obj, dict): encoded_dict = {} allowed_keys = set(obj.keys()) for key, value in obj.items(): if key in allowed_keys: encoded_key = jsonable_encoder(key, custom_encoder=custom_encoder) encoded_value = jsonable_encoder(value, custom_encoder=custom_encoder) encoded_dict[encoded_key] = encoded_value return encoded_dict if isinstance(obj, (list, set, frozenset, GeneratorType, tuple)): encoded_list = [] for item in obj: encoded_list.append(jsonable_encoder(item, custom_encoder=custom_encoder)) return encoded_list def fallback_serializer(o: Any) -> Any: attempt_encode = encode_by_type(o) if attempt_encode is not None: return attempt_encode try: data = dict(o) except Exception as e: errors: List[Exception] = [] errors.append(e) try: data = vars(o) except Exception as e: errors.append(e) raise ValueError(errors) from e return jsonable_encoder(data, custom_encoder=custom_encoder) return to_jsonable_with_fallback(obj, fallback_serializer)