Skip to content

Commit

Permalink
Merge pull request #130 from ragsagar/custom_encoder
Browse files Browse the repository at this point in the history
Attribute for setting JSON Encoder class in JSONResponseMixin
  • Loading branch information
kennethlove committed Mar 24, 2014
2 parents 3893d94 + 032e5e6 commit 116054d
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 3 deletions.
5 changes: 3 additions & 2 deletions braces/views/_ajax.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(),
Expand Down Expand Up @@ -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(
Expand Down
30 changes: 30 additions & 0 deletions docs/other.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions tests/helpers.py
Original file line number Diff line number Diff line change
@@ -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):
Expand Down Expand Up @@ -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)


10 changes: 9 additions & 1 deletion tests/test_ajax_mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions tests/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()),

Expand Down
13 changes: 13 additions & 0 deletions tests/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from .models import Article, CanonicalArticle
from .forms import ArticleForm, FormWithUserKwarg
from .helpers import SetJSONEncoder


class OkView(View):
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 116054d

Please sign in to comment.