diff --git a/django/contrib/messages/storage/cookie.py b/django/contrib/messages/storage/cookie.py
index a318002127..ca1ae7f6b6 100644
--- a/django/contrib/messages/storage/cookie.py
+++ b/django/contrib/messages/storage/cookie.py
@@ -33,6 +33,9 @@ class MessageDecoder(json.JSONDecoder):
def process_messages(self, obj):
if isinstance(obj, list) and obj:
if obj[0] == MessageEncoder.message_key:
+ if len(obj) == 3:
+ # Compatibility with previously-encoded messages
+ return Message(*obj[1:])
if obj[1]:
obj[3] = mark_safe(obj[3])
return Message(*obj[2:])
diff --git a/django/contrib/messages/tests/test_cookie.py b/django/contrib/messages/tests/test_cookie.py
index d44dd94491..10082634f6 100644
--- a/django/contrib/messages/tests/test_cookie.py
+++ b/django/contrib/messages/tests/test_cookie.py
@@ -153,3 +153,25 @@ class CookieTest(BaseTests, TestCase):
encode_decode(mark_safe("Hello Django!")), SafeData)
self.assertNotIsInstance(
encode_decode("Hello Django!"), SafeData)
+
+ def test_pre_1_5_message_format(self):
+ """
+ For ticket #22426. Tests whether messages that were set in the cookie
+ before the addition of is_safedata are decoded correctly.
+ """
+
+ # Encode the messages using the current encoder.
+ messages = [Message(constants.INFO, 'message %s') for x in range(5)]
+ encoder = MessageEncoder(separators=(',', ':'))
+ encoded_messages = encoder.encode(messages)
+
+ # Remove the is_safedata flag from the messages in order to imitate
+ # the behavior of before 1.5 (monkey patching).
+ encoded_messages = json.loads(encoded_messages)
+ for obj in encoded_messages:
+ obj.pop(1)
+ encoded_messages = json.dumps(encoded_messages, separators=(',', ':'))
+
+ # Decode the messages in the old format (without is_safedata)
+ decoded_messages = json.loads(encoded_messages, cls=MessageDecoder)
+ self.assertEqual(messages, decoded_messages)