Is there any simple way to override DjangoJSONEncoder.ensure_ascii
and set it to False
or output non-ascii text in django.http.JsonResponse
in any other way?
4 Answers
As of Django 1.9 you can configure JSONResponse
to disable the ensure_ascii
switch, by passing in a value for the json_dumps_params
argument:
return JsonResponse(response_data, safe=False, json_dumps_params={'ensure_ascii': False})
With ensure_ascii=False
, json.dumps()
outputs UTF-8 data for non-ASCII codepoints.
You could subclass JsonResponse
to make it the default unless set differently:
from django.http.response import JsonResponse
class UTF8JsonResponse(JsonResponse):
def __init__(self, *args, json_dumps_params=None, **kwargs):
json_dumps_params = {"ensure_ascii": False, **(json_dumps_params or {})}
super().__init__(*args, json_dumps_params=json_dumps_params, **kwargs)
then use that throughout instead of JsonResponse.
At the extreme end, you could monkey-patch the class to set ensure_ascii
to False
by default; put the following in a suitable module of your Django app (say, in a file named patches.py
):
import logging
from functools import wraps
from django.http.response import JsonResponse
logger = logging.getLogger(__name__)
def patch_jsonresponse_disable_ensure_ascii():
if getattr(JsonResponse, '_utf8_patched', False):
# Already patched. Add warning in logs with stack to see what location
# is trying to patch this a second time.
logger.warning("JSONResponse UTF8 patch already applied", stack_info=True)
return
logger.debug("Patching JSONResponse to disable ensure_ascii")
orig_init = JsonResponse.__init__
@wraps(orig_init)
def utf8_init(self, *args, json_dumps_params=None, **kwargs):
json_dumps_params = {"ensure_ascii": False, **(json_dumps_params or {})}
orig_init(self, *args, json_dumps_params=json_dumps_params, **kwargs)
JsonResponse.__init__ = utf8_init
JsonResponse._utf8_patched = True # to prevent accidental re-patching
then import patch_jsonresponse_disable_ensure_ascii
into your Django settings file and call it based on your desired config:
from yourapp.patches import patch_jsonresponse_disable_ensure_ascii
JSON_RESPONSES_UTF8 = True
if JSON_RESPONSES_UTF8:
patch_jsonresponse_disable_ensure_ascii()

- 363
- 5
- 10

- 1,048,767
- 296
- 4,058
- 3,343
-
2Is there any setting item to set that to False golbally instead of put that in every JsonResponse? – Jcyrss Apr 10 '20 at 03:20
-
@Jcyrss: expanded my answer to give you some more gradations, including monkeypatching Django itself to always set the flag to false. – Martijn Pieters Apr 10 '20 at 11:47
EDIT:
Or if you tend to the utf-8 format, use instead of Django's JsonResponse():
return HttpResponse(json.dumps(response_data, ensure_ascii=False),
content_type="application/json")
or
return JsonResponse(json.dumps(response_data, ensure_ascii=False), safe=False)
more about the safe=False
HERE
OLD:
You don't have to whatever alter.
Although Django creates JSON data in ASCII (from UTF-8), Javascript will automatically decode it back to UTF-8.

- 14,455
- 21
- 138
- 171

- 476
- 3
- 9
-
Thanks for the suggestion, but I prefer readability over slightly better backward compatibility that I don't need at all in my case. Also, UTF-8 is recommended in RFC 7159. – int_ua Jan 15 '16 at 15:07
-
1`JsonResponse(json.dumps(response_data, ensure_ascii=False), ...)` **doesn't work** as this **double-encodes the data**. There is no point in s etting `safe=False` in that case *either*, as that flag applies to what is accepted when encoding the data to JSON. Since you already encoded all objects to a JSON string, there are no 'unsafe' objects to encode anymore. – Martijn Pieters Nov 09 '19 at 16:13
from django.core.serializers.json import DjangoJSONEncoder
from django.http import JsonResponse
class MyJsonResponse(JsonResponse):
def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs):
json_dumps_params = dict(ensure_ascii=False)
super().__init__(data, encoder, safe, json_dumps_params, **kwargs)

- 353
- 1
- 3
- 10
-
This could be improved by allowing for `json_dumps_params` to be overridden. – Martijn Pieters Apr 10 '20 at 11:30
I didn't find any better way yet than to utilize an already installed REST Framework:
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from rest_framework.response import Response
from .models import INITIATOR_TYPES
@api_view(['GET'])
@permission_classes((IsAuthenticatedOrReadOnly, ))
def initiator_types(request):
data = {t[0]: str(t[1]) for t in INITIATOR_TYPES}
return Response(data)
But I don't really like it. It's much more complicated than JsonResponse
: https://stackoverflow.com/a/24411716/854477
-
-
It's a solution that I decided to share and simultaneously try searching for a better one. – int_ua Jan 14 '16 at 20:11