diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py
index 5d840d0c52effbf6963a65ea0599c3fb558653ba..06e7ee839bb5e33dce74b4045c70c6e1e40b2f78 100644
--- a/aleksis/core/settings.py
+++ b/aleksis/core/settings.py
@@ -10,8 +10,11 @@ from .util.core_helpers import (
     lazy_get_favicons,
     lazy_preference,
     merge_app_settings,
+    monkey_patch,
 )
 
+monkey_patch()
+
 IN_PYTEST = "PYTEST_CURRENT_TEST" in os.environ or "TOX_ENV_DIR" in os.environ
 
 ENVVAR_PREFIX_FOR_DYNACONF = "ALEKSIS"
diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py
index 9ad3b70c3ebb85dead30b617eedf279543be536e..9c5f93a1f1e43d38a3aebba75d2e00b7cdda7bfe 100644
--- a/aleksis/core/util/core_helpers.py
+++ b/aleksis/core/util/core_helpers.py
@@ -261,3 +261,16 @@ def queryset_rules_filter(
 def unread_notifications_badge(request: HttpRequest) -> int:
     """Generate badge content with the number of unread notifications."""
     return request.user.person.unread_notifications_count
+
+
+def monkey_patch() -> None:  # noqa
+    """Monkey-patch dependencies for special behaviour."""
+    # Unwrap promises in JSON serializer instead of stringifying
+    import django.core.serializers.json
+    from django.utils.functional import Promise
+    class DjangoJSONEncoder(json.DjangoJSONEncoder):
+        def default(self, o: Any) -> Any:
+            if isinstance(o, Promise) and hasattr(o, copy):
+                return super().default(o.copy())
+            return super().default(o)
+    json.DjangoJSONEncoder = DjangoJSONEncoder