Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating UTF-8 JsonResponse in Django

Tags:

json

utf-8

django

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?

like image 697
int_ua Avatar asked Jan 14 '16 20:01

int_ua


2 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()
like image 193
Martijn Pieters Avatar answered Sep 20 '22 14:09

Martijn Pieters


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.

like image 32
Yaaaaaaaaaaay Avatar answered Sep 18 '22 14:09

Yaaaaaaaaaaay