Improve topic sorting: add popular sorting by publications and authors count
This commit is contained in:
@@ -1,28 +1,118 @@
|
||||
from decimal import Decimal
|
||||
from json import JSONEncoder
|
||||
"""
|
||||
JSON encoders and utilities
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import decimal
|
||||
from typing import Any, Union
|
||||
|
||||
import orjson
|
||||
|
||||
|
||||
class CustomJSONEncoder(JSONEncoder):
|
||||
def default_json_encoder(obj: Any) -> Any:
|
||||
"""
|
||||
Расширенный JSON энкодер с поддержкой сериализации объектов SQLAlchemy.
|
||||
Default JSON encoder для объектов, которые не поддерживаются стандартным JSON
|
||||
|
||||
Примеры:
|
||||
>>> import json
|
||||
>>> from decimal import Decimal
|
||||
>>> from orm.topic import Topic
|
||||
>>> json.dumps(Decimal("10.50"), cls=CustomJSONEncoder)
|
||||
'"10.50"'
|
||||
>>> topic = Topic(id=1, slug="test")
|
||||
>>> json.dumps(topic, cls=CustomJSONEncoder)
|
||||
'{"id": 1, "slug": "test", ...}'
|
||||
Args:
|
||||
obj: Объект для сериализации
|
||||
|
||||
Returns:
|
||||
Сериализуемое представление объекта
|
||||
|
||||
Raises:
|
||||
TypeError: Если объект не может быть сериализован
|
||||
"""
|
||||
if hasattr(obj, "dict") and callable(obj.dict):
|
||||
return obj.dict()
|
||||
if hasattr(obj, "__dict__"):
|
||||
return obj.__dict__
|
||||
if isinstance(obj, (datetime.datetime, datetime.date, datetime.time)):
|
||||
return obj.isoformat()
|
||||
if isinstance(obj, decimal.Decimal):
|
||||
return float(obj)
|
||||
if hasattr(obj, "__json__"):
|
||||
return obj.__json__()
|
||||
msg = f"Object of type {type(obj)} is not JSON serializable"
|
||||
raise TypeError(msg)
|
||||
|
||||
def default(self, obj):
|
||||
if isinstance(obj, Decimal):
|
||||
return str(obj)
|
||||
|
||||
# Проверяем, есть ли у объекта метод dict() (как у моделей SQLAlchemy)
|
||||
if hasattr(obj, "dict") and callable(obj.dict):
|
||||
return obj.dict()
|
||||
def orjson_dumps(obj: Any, **kwargs: Any) -> bytes:
|
||||
"""
|
||||
Сериализует объект в JSON с помощью orjson
|
||||
|
||||
return super().default(obj)
|
||||
Args:
|
||||
obj: Объект для сериализации
|
||||
**kwargs: Дополнительные параметры для orjson.dumps
|
||||
|
||||
Returns:
|
||||
bytes: JSON в виде байтов
|
||||
"""
|
||||
# Используем правильную константу для orjson
|
||||
option_flags = orjson.OPT_SERIALIZE_DATACLASS
|
||||
if kwargs.get("indent"):
|
||||
option_flags |= orjson.OPT_INDENT_2
|
||||
|
||||
return orjson.dumps(obj, default=default_json_encoder, option=option_flags)
|
||||
|
||||
|
||||
def orjson_loads(data: Union[str, bytes]) -> Any:
|
||||
"""
|
||||
Десериализует JSON с помощью orjson
|
||||
|
||||
Args:
|
||||
data: JSON данные в виде строки или байтов
|
||||
|
||||
Returns:
|
||||
Десериализованный объект
|
||||
"""
|
||||
return orjson.loads(data)
|
||||
|
||||
|
||||
class JSONEncoder:
|
||||
"""Кастомный JSON кодировщик на основе orjson"""
|
||||
|
||||
@staticmethod
|
||||
def encode(obj: Any) -> str:
|
||||
"""Encode object to JSON string"""
|
||||
return orjson_dumps(obj).decode("utf-8")
|
||||
|
||||
@staticmethod
|
||||
def decode(data: Union[str, bytes]) -> Any:
|
||||
"""Decode JSON string to object"""
|
||||
return orjson_loads(data)
|
||||
|
||||
|
||||
# Создаем экземпляр для обратной совместимости
|
||||
CustomJSONEncoder = JSONEncoder()
|
||||
|
||||
|
||||
def fast_json_dumps(obj: Any, indent: bool = False) -> str:
|
||||
"""
|
||||
Быстрая сериализация JSON
|
||||
|
||||
Args:
|
||||
obj: Объект для сериализации
|
||||
indent: Форматировать с отступами
|
||||
|
||||
Returns:
|
||||
JSON строка
|
||||
"""
|
||||
return orjson_dumps(obj, indent=indent).decode("utf-8")
|
||||
|
||||
|
||||
def fast_json_loads(data: Union[str, bytes]) -> Any:
|
||||
"""
|
||||
Быстрая десериализация JSON
|
||||
|
||||
Args:
|
||||
data: JSON данные
|
||||
|
||||
Returns:
|
||||
Десериализованный объект
|
||||
"""
|
||||
return orjson_loads(data)
|
||||
|
||||
|
||||
# Экспортируем для удобства
|
||||
dumps = fast_json_dumps
|
||||
loads = fast_json_loads
|
||||
|
Reference in New Issue
Block a user