2025-06-02 02:56:11 +03:00
|
|
|
|
"""
|
|
|
|
|
JSON encoders and utilities
|
|
|
|
|
"""
|
2024-03-06 21:57:04 +03:00
|
|
|
|
|
2025-07-31 18:55:59 +03:00
|
|
|
|
import json
|
|
|
|
|
from datetime import date, datetime
|
2025-06-02 02:56:11 +03:00
|
|
|
|
from typing import Any, Union
|
2025-03-20 11:55:21 +03:00
|
|
|
|
|
2025-06-02 02:56:11 +03:00
|
|
|
|
import orjson
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def default_json_encoder(obj: Any) -> Any:
|
|
|
|
|
"""
|
2025-07-31 18:55:59 +03:00
|
|
|
|
Кастомный JSON энкодер для сериализации нестандартных типов.
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
obj: Объект для сериализации
|
|
|
|
|
|
|
|
|
|
Returns:
|
2025-07-31 18:55:59 +03:00
|
|
|
|
Сериализованное представление объекта
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
|
TypeError: Если объект не может быть сериализован
|
|
|
|
|
"""
|
2025-07-31 18:55:59 +03:00
|
|
|
|
# Обработка datetime
|
|
|
|
|
if isinstance(obj, (datetime, date)):
|
2025-06-02 02:56:11 +03:00
|
|
|
|
return obj.isoformat()
|
2025-07-31 18:55:59 +03:00
|
|
|
|
|
|
|
|
|
serialized = False
|
|
|
|
|
|
|
|
|
|
# Обработка объектов с методом __json__
|
2025-06-02 02:56:11 +03:00
|
|
|
|
if hasattr(obj, "__json__"):
|
2025-07-31 18:55:59 +03:00
|
|
|
|
try:
|
|
|
|
|
result = obj.__json__()
|
|
|
|
|
serialized = True
|
|
|
|
|
return result
|
|
|
|
|
except Exception as _e:
|
|
|
|
|
serialized = False
|
|
|
|
|
|
|
|
|
|
# Обработка объектов с методом to_dict
|
|
|
|
|
if hasattr(obj, "to_dict"):
|
|
|
|
|
try:
|
|
|
|
|
result = obj.to_dict()
|
|
|
|
|
serialized = True
|
|
|
|
|
return result
|
|
|
|
|
except Exception as _e:
|
|
|
|
|
serialized = False
|
|
|
|
|
|
|
|
|
|
# Обработка объектов с методом dict
|
|
|
|
|
if hasattr(obj, "dict"):
|
|
|
|
|
try:
|
|
|
|
|
result = obj.dict()
|
|
|
|
|
serialized = True
|
|
|
|
|
return result
|
|
|
|
|
except Exception as _e:
|
|
|
|
|
serialized = False
|
|
|
|
|
|
|
|
|
|
# Если ни один из методов не сработал, вызываем TypeError
|
|
|
|
|
if not serialized:
|
|
|
|
|
error_text = f"Object of type {type(obj).__name__} is not JSON serializable"
|
|
|
|
|
raise TypeError(error_text)
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def orjson_dumps(obj: Any, **kwargs: Any) -> bytes:
|
|
|
|
|
"""
|
2025-07-31 18:55:59 +03:00
|
|
|
|
Сериализация объекта с помощью orjson.
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
obj: Объект для сериализации
|
2025-07-31 18:55:59 +03:00
|
|
|
|
**kwargs: Дополнительные параметры
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
|
|
|
|
Returns:
|
2025-07-31 18:55:59 +03:00
|
|
|
|
bytes: Сериализованный объект
|
2025-06-02 02:56:11 +03:00
|
|
|
|
"""
|
2025-07-31 18:55:59 +03:00
|
|
|
|
return orjson.dumps(obj, default=default_json_encoder, **kwargs)
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def orjson_loads(data: Union[str, bytes]) -> Any:
|
|
|
|
|
"""
|
2025-07-31 18:55:59 +03:00
|
|
|
|
Десериализация объекта с помощью orjson.
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
|
|
|
|
Args:
|
2025-07-31 18:55:59 +03:00
|
|
|
|
data: Строка или байты для десериализации
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Десериализованный объект
|
2025-03-20 12:52:44 +03:00
|
|
|
|
"""
|
2025-06-02 02:56:11 +03:00
|
|
|
|
return orjson.loads(data)
|
|
|
|
|
|
|
|
|
|
|
2025-07-31 18:55:59 +03:00
|
|
|
|
class JSONEncoder(json.JSONEncoder):
|
|
|
|
|
"""
|
|
|
|
|
Расширенный JSON энкодер с поддержкой кастомной сериализации.
|
|
|
|
|
"""
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
2025-07-31 18:55:59 +03:00
|
|
|
|
def default(self, obj: Any) -> Any:
|
|
|
|
|
"""
|
|
|
|
|
Метод для сериализации нестандартных типов.
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
2025-07-31 18:55:59 +03:00
|
|
|
|
Args:
|
|
|
|
|
obj: Объект для сериализации
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
2025-07-31 18:55:59 +03:00
|
|
|
|
Returns:
|
|
|
|
|
Сериализованное представление объекта
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
return default_json_encoder(obj)
|
|
|
|
|
except TypeError:
|
|
|
|
|
return super().default(obj)
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
2025-03-20 12:52:44 +03:00
|
|
|
|
|
2025-07-31 18:55:59 +03:00
|
|
|
|
def fast_json_dumps(obj: Any, **kwargs: Any) -> str:
|
2025-03-20 12:52:44 +03:00
|
|
|
|
"""
|
2025-07-31 18:55:59 +03:00
|
|
|
|
Быстрая сериализация объекта в JSON-строку.
|
2025-03-20 12:52:44 +03:00
|
|
|
|
|
2025-06-02 02:56:11 +03:00
|
|
|
|
Args:
|
|
|
|
|
obj: Объект для сериализации
|
2025-07-31 18:55:59 +03:00
|
|
|
|
**kwargs: Дополнительные параметры
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
|
|
|
|
Returns:
|
2025-07-31 18:55:59 +03:00
|
|
|
|
str: JSON-строка
|
2025-06-02 02:56:11 +03:00
|
|
|
|
"""
|
2025-07-31 18:55:59 +03:00
|
|
|
|
return json.dumps(obj, cls=JSONEncoder, **kwargs)
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
|
|
|
|
|
2025-07-31 18:55:59 +03:00
|
|
|
|
def fast_json_loads(data: str, **kwargs: Any) -> Any:
|
2025-06-02 02:56:11 +03:00
|
|
|
|
"""
|
2025-07-31 18:55:59 +03:00
|
|
|
|
Быстрая десериализация JSON-строки.
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
|
|
|
|
Args:
|
2025-07-31 18:55:59 +03:00
|
|
|
|
data: JSON-строка
|
|
|
|
|
**kwargs: Дополнительные параметры
|
2025-06-02 02:56:11 +03:00
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Десериализованный объект
|
|
|
|
|
"""
|
2025-07-31 18:55:59 +03:00
|
|
|
|
return json.loads(data, **kwargs)
|