From d6ea4898c44f75a25bc0b7a60b54fd6dddc69eb5 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Thu, 6 Jun 2019 21:40:15 -0700 Subject: [PATCH] Fixed #30550 -- Fixed decoding of non-UTF-8 bytes objects in response.json(). --- django/test/client.py | 2 +- tests/test_client_regress/tests.py | 5 +++++ tests/test_client_regress/urls.py | 1 + tests/test_client_regress/views.py | 4 ++++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/django/test/client.py b/django/test/client.py index bb4fb93c45..1eb2e2dd06 100644 --- a/django/test/client.py +++ b/django/test/client.py @@ -650,7 +650,7 @@ class Client(RequestFactory): 'Content-Type header is "{0}", not "application/json"' .format(response.get('Content-Type')) ) - response._json = json.loads(response.content.decode(), **extra) + response._json = json.loads(response.content.decode(response.charset), **extra) return response._json def _handle_redirects(self, response, data='', content_type='', **extra): diff --git a/tests/test_client_regress/tests.py b/tests/test_client_regress/tests.py index 568317ec26..0763ae67b1 100644 --- a/tests/test_client_regress/tests.py +++ b/tests/test_client_regress/tests.py @@ -1204,6 +1204,11 @@ class RequestMethodStringDataTests(SimpleTestCase): response = self.client.get('/json_response/') self.assertEqual(response.json(), {'key': 'value'}) + def test_json_charset(self): + response = self.client.get('/json_response_latin1/') + self.assertEqual(response.charset, 'latin1') + self.assertEqual(response.json(), {'a': 'Å'}) + def test_json_structured_suffixes(self): valid_types = ( 'application/vnd.api+json', diff --git a/tests/test_client_regress/urls.py b/tests/test_client_regress/urls.py index 18c037bc23..8590e5953a 100644 --- a/tests/test_client_regress/urls.py +++ b/tests/test_client_regress/urls.py @@ -31,6 +31,7 @@ urlpatterns = [ path('check_unicode/', views.return_unicode), path('check_binary/', views.return_undecodable_binary), path('json_response/', views.return_json_response), + path('json_response_latin1/', views.return_json_response_latin1), path('parse_encoded_text/', views.return_text_file), path('check_headers/', views.check_headers), path('check_headers_redirect/', RedirectView.as_view(url='/check_headers/')), diff --git a/tests/test_client_regress/views.py b/tests/test_client_regress/views.py index 4758283ef9..94b0ab29a8 100644 --- a/tests/test_client_regress/views.py +++ b/tests/test_client_regress/views.py @@ -109,6 +109,10 @@ def return_json_response(request): return JsonResponse({'key': 'value'}, **kwargs) +def return_json_response_latin1(request): + return HttpResponse(b'{"a":"\xc5"}', content_type='application/json; charset=latin1') + + def return_text_file(request): "A view that parses and returns text as a file." match = CONTENT_TYPE_RE.match(request.META['CONTENT_TYPE'])