From b63c387806f8250f5dfd69572136bc784c67593a Mon Sep 17 00:00:00 2001 From: Untone Date: Thu, 20 Mar 2025 12:52:44 +0300 Subject: [PATCH] jsonfix3 --- CHANGELOG.md | 5 +++++ cache/memorycache.py | 13 ++++++++++++- utils/encoders.py | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57c736da..32793427 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +#### [0.4.13] - 2025-03-20 +- Fixed Topic objects serialization error in cache/memorycache.py +- Improved CustomJSONEncoder to support SQLAlchemy models with dict() method +- Enhanced error handling in cache_on_arguments decorator + #### [0.4.12] - 2025-03-19 - `delete_reaction` detects comments and uses `deleted_at` update - `check_to_unfeature` etc. update diff --git a/cache/memorycache.py b/cache/memorycache.py index d2b666d9..80035ea6 100644 --- a/cache/memorycache.py +++ b/cache/memorycache.py @@ -99,10 +99,21 @@ class RedisCache: try: import asyncio - serialized = json.dumps(result, cls=CustomJSONEncoder) + # Попытка сериализовать результат в JSON + try: + serialized = json.dumps(result, cls=CustomJSONEncoder) + except (TypeError, ValueError) as e: + logger.debug(f"JSON сериализация не удалась, используем pickle: {e}") + # Если не удалось сериализовать как JSON, используем pickle + serialized = pickle.dumps(result).decode() + asyncio.create_task(redis.set(key, serialized, ex=self.ttl)) except Exception as e: logger.error(f"Ошибка при кешировании результата: {e}") + # Для отладки добавляем информацию о типе объекта + logger.debug(f"Тип результата: {type(result)}") + if hasattr(result, "__class__"): + logger.debug(f"Класс результата: {result.__class__.__name__}") return result diff --git a/utils/encoders.py b/utils/encoders.py index 13964b07..e93cc763 100644 --- a/utils/encoders.py +++ b/utils/encoders.py @@ -3,7 +3,26 @@ from json import JSONEncoder class CustomJSONEncoder(JSONEncoder): + """ + Расширенный JSON энкодер с поддержкой сериализации объектов SQLAlchemy. + + Примеры: + >>> 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", ...}' + """ + def default(self, obj): if isinstance(obj, Decimal): return str(obj) + + # Проверяем, есть ли у объекта метод dict() (как у моделей SQLAlchemy) + if hasattr(obj, "dict") and callable(obj.dict): + return obj.dict() + return super().default(obj)