Skip to content

Commit f396732

Browse files
Allow application to provide a custom JSON encoder/decoder.
1 parent b5ada8c commit f396732

File tree

3 files changed

+45
-4
lines changed

3 files changed

+45
-4
lines changed

socketio/packet.py

100644100755
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import functools
2-
import json
2+
import json as _json
33

44
import six
55

@@ -11,6 +11,9 @@
1111

1212
class Packet(object):
1313
"""Socket.IO packet."""
14+
15+
json = _json
16+
1417
def __init__(self, packet_type=EVENT, data=None, namespace=None, id=None,
1518
binary=None, encoded_packet=None):
1619
self.packet_type = packet_type
@@ -54,7 +57,7 @@ def encode(self):
5457
if data is not None:
5558
if needs_comma:
5659
encoded_packet += ','
57-
encoded_packet += json.dumps(data, separators=(',', ':'))
60+
encoded_packet += self.json.dumps(data, separators=(',', ':'))
5861
if attachments is not None:
5962
encoded_packet = [encoded_packet] + attachments
6063
return encoded_packet
@@ -90,7 +93,7 @@ def decode(self, encoded_packet):
9093
self.id = self.id * 10 + int(ep[0])
9194
ep = ep[1:]
9295
if ep:
93-
self.data = json.loads(ep)
96+
self.data = self.json.loads(ep)
9497
return attachment_count
9598

9699
def reconstruct_binary(self, attachments):

socketio/server.py

100644100755
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ class Server(object):
2828
``bytes`` values are treated as binary. This option has no
2929
effect on Python 3, where text and binary payloads are
3030
always automatically discovered.
31+
:param json: An alternative json module to use for encoding and decoding
32+
packets. Custom json modules must have ``dumps`` and ``loads``
33+
functions that are compatible with the standard library
34+
versions.
3135
:param kwargs: Connection parameters for the underlying Engine.IO server.
3236
3337
The Engine.IO configuration supports the following settings:
@@ -60,14 +64,17 @@ class Server(object):
6064
``False``.
6165
"""
6266
def __init__(self, client_manager_class=None, logger=False, binary=False,
63-
**kwargs):
67+
json=None, **kwargs):
6468
if client_manager_class is None:
6569
client_manager_class = base_manager.BaseManager
6670
self.manager = client_manager_class(self)
6771
engineio_options = kwargs
6872
engineio_logger = engineio_options.pop('engineio_logger', None)
6973
if engineio_logger is not None:
7074
engineio_options['logger'] = engineio_logger
75+
if json is not None:
76+
packet.Packet.json = json
77+
engineio_options['json'] = json
7178
self.eio = engineio.Server(**engineio_options)
7279
self.eio.on('connect', self._handle_eio_connect)
7380
self.eio.on('message', self._handle_eio_message)

tests/test_server.py

100644100755
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import logging
23
import unittest
34

@@ -7,11 +8,16 @@
78
else:
89
import mock
910

11+
from socketio import packet
1012
from socketio import server
1113

1214

1315
@mock.patch('engineio.Server')
1416
class TestServer(unittest.TestCase):
17+
def tearDown(self):
18+
# restore JSON encoder, in case a test changed it
19+
packet.Packet.json = json
20+
1521
def test_create(self, eio):
1622
mgr = mock.MagicMock()
1723
s = server.Server(mgr, binary=True, foo='bar')
@@ -374,3 +380,28 @@ def test_logger(self, eio):
374380
def test_engineio_logger(self, eio):
375381
server.Server(engineio_logger='foo')
376382
eio.assert_called_once_with(**{'logger': 'foo'})
383+
384+
def test_custom_json(self, eio):
385+
# Warning: this test cannot run in parallel with other tests, as it
386+
# changes the JSON encoding/decoding functions
387+
388+
class CustomJSON(object):
389+
@staticmethod
390+
def dumps(*args, **kwargs):
391+
return '*** encoded ***'
392+
393+
@staticmethod
394+
def loads(*args, **kwargs):
395+
return '+++ decoded +++'
396+
397+
server.Server(json=CustomJSON)
398+
eio.assert_called_once_with(**{'json': CustomJSON})
399+
400+
pkt = packet.Packet(packet_type=packet.EVENT,
401+
data={six.text_type('foo'): six.text_type('bar')})
402+
self.assertEqual(pkt.encode(), '2*** encoded ***')
403+
pkt2 = packet.Packet(encoded_packet=pkt.encode())
404+
self.assertEqual(pkt2.data, '+++ decoded +++')
405+
406+
# restore the default JSON module
407+
packet.Packet.json = json

0 commit comments

Comments
 (0)