From dc4bed6d614870a68d96ebebe48b41a49ca12aea Mon Sep 17 00:00:00 2001 From: "Rag Sagar.V" Date: Wed, 5 Mar 2014 08:41:15 +0400 Subject: [PATCH 1/3] Adding attribute in JSONResponseMixin to set custom JSON encoder class --- braces/views/_ajax.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/braces/views/_ajax.py b/braces/views/_ajax.py index 7044a5cc..fbec6016 100644 --- a/braces/views/_ajax.py +++ b/braces/views/_ajax.py @@ -19,6 +19,7 @@ class JSONResponseMixin(object): """ content_type = None json_dumps_kwargs = None + json_encoder_class = DjangoJSONEncoder def get_content_type(self): if (self.content_type is not None and @@ -43,7 +44,7 @@ def render_json_response(self, context_dict, status=200): """ json_context = json.dumps( context_dict, - cls=DjangoJSONEncoder, + cls=self.json_encoder_class, **self.get_json_dumps_kwargs()).encode(u'utf-8') return HttpResponse(json_context, content_type=self.get_content_type(), @@ -118,7 +119,7 @@ def render_bad_request_response(self, error_dict=None): error_dict = self.error_response_dict json_context = json.dumps( error_dict, - cls=DjangoJSONEncoder, + cls=self.json_encoder_class, **self.get_json_dumps_kwargs() ).encode(u'utf-8') return HttpResponseBadRequest( From 08ae8527f3c5dca2ae2d8b445eceb5feb79c60d3 Mon Sep 17 00:00:00 2001 From: "Rag Sagar.V" Date: Wed, 5 Mar 2014 08:41:53 +0400 Subject: [PATCH 2/3] Adding test for json_encoder_class attribute in JSONResponseMixin --- tests/helpers.py | 14 ++++++++++++++ tests/test_ajax_mixins.py | 10 +++++++++- tests/urls.py | 1 + tests/views.py | 13 +++++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/tests/helpers.py b/tests/helpers.py index 27b551f6..643772a2 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,5 +1,6 @@ from django import test from django.contrib.auth.models import AnonymousUser +from django.core.serializers.json import DjangoJSONEncoder class TestViewHelper(object): @@ -47,3 +48,16 @@ def dispatch_view(self, request, args=None, kwargs=None, view_class=None, """ view = self.build_view(request, args, kwargs, view_class, **viewkwargs) return view.dispatch(request, *view.args, **view.kwargs) + + +class SetJSONEncoder(DjangoJSONEncoder): + """ + A custom JSONEncoder extending `DjangoJSONEncoder` to handle serialization + of `set`. + """ + def default(self, obj): + if isinstance(obj, set): + return list(obj) + return super(DjangoJSONEncoder, self).default(obj) + + diff --git a/tests/test_ajax_mixins.py b/tests/test_ajax_mixins.py index e0b3aa82..9e1a0bab 100644 --- a/tests/test_ajax_mixins.py +++ b/tests/test_ajax_mixins.py @@ -11,7 +11,8 @@ from .compat import force_text from .factories import ArticleFactory, UserFactory from .helpers import TestViewHelper -from .views import SimpleJsonView, JsonRequestResponseView +from .views import (SimpleJsonView, JsonRequestResponseView, + CustomJsonEncoderView) from .compat import json @@ -136,6 +137,13 @@ def test_pretty_json(self): self.assertEqual(normal_json, pretty_json) self.assertTrue(len(pretty_content) > len(normal_content)) + def test_json_encoder_class_atrribute(self): + """ + Tests setting custom `json_encoder_class` attribute. + """ + data = json.loads(self.get_content(u'/simple_json_custom_encoder/')) + self.assertEqual({u'numbers': [1, 2, 3]}, data) + class TestJsonRequestResponseMixin(TestViewHelper, test.TestCase): view_class = JsonRequestResponseView diff --git a/tests/urls.py b/tests/urls.py index e3ef448c..6326ceab 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -80,6 +80,7 @@ # JSONResponseMixin tests url(r'^simple_json/$', views.SimpleJsonView.as_view()), + url(r'^simple_json_custom_encoder/$', views.CustomJsonEncoderView.as_view()), url(r'^simple_json_400/$', views.SimpleJsonBadRequestView.as_view()), url(r'^article_list_json/$', views.ArticleListJsonView.as_view()), diff --git a/tests/views.py b/tests/views.py index 64895de5..1097c9a0 100644 --- a/tests/views.py +++ b/tests/views.py @@ -12,6 +12,7 @@ from .models import Article, CanonicalArticle from .forms import ArticleForm, FormWithUserKwarg +from .helpers import SetJSONEncoder class OkView(View): @@ -79,6 +80,18 @@ def get(self, request): return self.render_json_response(object) +class CustomJsonEncoderView(views.JSONResponseMixin, View): + """ + A view for testing JSONResponseMixin's `json_encoder_class` attribute + with custom JSONEncoder class. + """ + json_encoder_class = SetJSONEncoder + + def get(self, request): + object = {'numbers': set([1, 2, 3])} + return self.render_json_response(object) + + class SimpleJsonBadRequestView(views.JSONResponseMixin, View): """ A view for testing JSONResponseMixin's render_json_response() method with From 032e5e6db4c4aa9413a09f0cbaa1dab483ee17e9 Mon Sep 17 00:00:00 2001 From: "Rag Sagar.V" Date: Wed, 5 Mar 2014 08:42:43 +0400 Subject: [PATCH 3/3] Adding doc for json_encoder_class attribute in JSONResponseMixin --- docs/other.rst | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/other.rst b/docs/other.rst index a97392db..1e5508e5 100644 --- a/docs/other.rst +++ b/docs/other.rst @@ -225,6 +225,36 @@ overriding the `get_content_type()` method. # Shown just for illustrative purposes return u"application/javascript" +The `JSONResponseMixin` provides another class-level variable +`json_encoder_class` to use a custom json encoder with `json.dumps`. +By default it is `django.core.serializers.json.DjangoJsonEncoder` + +:: + + from django.core.serializers.json import DjangoJSONEncoder + + from braces.views import JSONResponseMixin + + + class SetJSONEncoder(DjangoJSONEncoder): + """ + A custom JSONEncoder extending `DjangoJSONEncoder` to handle serialization + of `set`. + """ + def default(self, obj): + if isinstance(obj, set): + return list(obj) + return super(DjangoJSONEncoder, self).default(obj) + + + class GetSetDataView(JSONResponseMixin, View): + json_encoder_class = SetJSONEncoder + + def get(self, request, *args, **kwargs): + numbers_set = set(range(10)) + data = {'numbers': numbers_set} + return self.render_json_response(data) + .. _JsonRequestResponseMixin: JsonRequestResponseMixin