Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for custom JSON serializer #3

Merged
merged 4 commits into from Feb 3, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 8 additions & 1 deletion docs/apidocs/index.txt
Expand Up @@ -70,6 +70,13 @@ functionality of RPC4Django
allowing cross site requests. See the Mozilla documentation on
`preflighted requests`_ for more details. Defaults to the empty string.

.. envvar:: RPC4DJANGO_JSON_ENCODER

Subclass of ``rpc4django.jsonrpcdispatcher.json.JSONEncoder`` or string
pointing to the subclass. It can be used to serialize objects that can't
otherwise be serialized. Defaults to
``django.core.serializers.json.DjangoJSONEncoder``.

.. _requests with credentials: https://developer.mozilla.org/en/HTTP_access_control#Requests_with_credentials
.. _preflighted requests: https://developer.mozilla.org/en/HTTP_access_control#Preflighted_requests

Expand Down Expand Up @@ -102,4 +109,4 @@ Template tags

.. automodule:: rpc4django.templatetags.rpctags
:members:


10 changes: 5 additions & 5 deletions rpc4django/jsonrpcdispatcher.py
Expand Up @@ -40,7 +40,8 @@ class JSONRPCDispatcher:
or error.
'''

def __init__(self):
def __init__(self,json_encoder):
self.json_encoder = json_encoder
self.methods = {}

def register_function(self, method, external_name):
Expand All @@ -61,17 +62,16 @@ def _encode_result(self, jsonid, result, error):
res['error'] = error
res['error']['name'] = 'JSONRPCError'
res['result'] = None

try:
return json.dumps(res, indent=JSON_INDENT)
return json.dumps(res, indent=JSON_INDENT, cls=self.json_encoder)
except:
err = {'message': 'failed to encode return value',
'code': JSONRPC_SERVICE_ERROR,
'name': 'JSONRPCError'}

res['result'] = None
res['error'] = err
return json.dumps(res, indent=JSON_INDENT)
return json.dumps(res, indent=JSON_INDENT, cls=self.json_encoder)

def dispatch(self, json_data, **kwargs):
'''
Expand Down Expand Up @@ -146,4 +146,4 @@ def dispatch(self, json_data, **kwargs):
'" is not supported',
'code': JSONRPC_PROCEDURE_NOT_FOUND_ERROR})



5 changes: 3 additions & 2 deletions rpc4django/rpcdispatcher.py
Expand Up @@ -210,11 +210,12 @@ class RPCDispatcher:

'''

def __init__(self, url='', apps=[], restrict_introspection=False, restrict_ootb_auth=True):
def __init__(self, url='', apps=[], restrict_introspection=False,
restrict_ootb_auth=True, json_encoder=None):
version = platform.python_version_tuple()
self.url = url
self.rpcmethods = [] # a list of RPCMethod objects
self.jsonrpcdispatcher = JSONRPCDispatcher()
self.jsonrpcdispatcher = JSONRPCDispatcher(json_encoder)
self.xmlrpcdispatcher = XMLRPCDispatcher()

if not restrict_introspection:
Expand Down
23 changes: 20 additions & 3 deletions rpc4django/views.py
Expand Up @@ -17,8 +17,10 @@
from django.http import HttpResponse, Http404, HttpResponseForbidden
from django.shortcuts import render_to_response
from django.conf import settings
from django.core.urlresolvers import reverse, NoReverseMatch
from django.core.urlresolvers import reverse, NoReverseMatch, get_mod_func
from django.utils.importlib import import_module
from rpcdispatcher import RPCDispatcher
from jsonrpcdispatcher import json
from __init__ import version

logger = logging.getLogger('rpc4django')
Expand All @@ -42,6 +44,8 @@
'RPC4DJANGO_HTTP_ACCESS_CREDENTIALS', False)
HTTP_ACCESS_ALLOW_ORIGIN = getattr(settings,
'RPC4DJANGO_HTTP_ACCESS_ALLOW_ORIGIN', '')
JSON_ENCODER = getattr(settings, 'RPC4DJANGO_JSON_ENCODER',
'django.core.serializers.json.DjangoJSONEncoder')

# get a list of the installed django applications
# these will be scanned for @rpcmethod decorators
Expand Down Expand Up @@ -232,8 +236,21 @@ def serve_rpc_request(request):
URL = reverse(serve_rpc_request)
except NoReverseMatch:
URL = ''


# resolve JSON_ENCODER to class if it's a string
if isinstance(JSON_ENCODER, basestring):
mod_name, cls_name = get_mod_func(JSON_ENCODER)
json_encoder = getattr(import_module(mod_name), cls_name)
else:
json_encoder = JSON_ENCODER


if not issubclass(json_encoder, json.JSONEncoder):
raise Exception("RPC4DJANGO_JSON_ENCODER must be derived from "
"rpc4django.jsonrpcdispatcher.JSONEncoder")

# instantiate the rpcdispatcher -- this examines the INSTALLED_APPS
# for any @rpcmethod decorators and adds them to the callable methods
dispatcher = RPCDispatcher(URL, APPS, RESTRICT_INTROSPECTION, RESTRICT_OOTB_AUTH)
dispatcher = RPCDispatcher(URL, APPS, RESTRICT_INTROSPECTION,
RESTRICT_OOTB_AUTH, json_encoder)