Skip to content

Commit

Permalink
add use_binary_hex_encoding option on json object serializer (#1467)
Browse files Browse the repository at this point in the history
add use_binary_hex_encoding option on json object serializer
  • Loading branch information
oberstet committed Feb 26, 2021
1 parent 87ae2be commit 9ca21af
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 14 deletions.
54 changes: 40 additions & 14 deletions autobahn/wamp/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import struct
import platform
import math
from binascii import b2a_hex, a2b_hex

from txaio import time_ns
from autobahn.wamp.interfaces import IObjectSerializer, ISerializer
Expand Down Expand Up @@ -343,9 +344,20 @@ def unserialize(self, payload, isBinary=None):

class _WAMPJsonEncoder(json.JSONEncoder):

def __init__(self, *args, **kwargs):
if 'use_binary_hex_encoding' in kwargs:
self._use_binary_hex_encoding = kwargs['use_binary_hex_encoding']
del kwargs['use_binary_hex_encoding']
else:
self._use_binary_hex_encoding = False
json.JSONEncoder.__init__(self, *args, **kwargs)

def default(self, obj):
if isinstance(obj, bytes):
return '\x00' + base64.b64encode(obj).decode('ascii')
if self._use_binary_hex_encoding:
return '0x' + b2a_hex(obj).decode('ascii')
else:
return '\x00' + base64.b64encode(obj).decode('ascii')
else:
return json.JSONEncoder.default(self, obj)

Expand All @@ -356,16 +368,27 @@ def default(self, obj):
from json import scanner
from json.decoder import scanstring

def _parse_string(*args, **kwargs):
s, idx = scanstring(*args, **kwargs)
if s and s[0] == '\x00':
s = base64.b64decode(s[1:])
return s, idx

class _WAMPJsonDecoder(json.JSONDecoder):

def __init__(self, *args, **kwargs):
if 'use_binary_hex_encoding' in kwargs:
self._use_binary_hex_encoding = kwargs['use_binary_hex_encoding']
del kwargs['use_binary_hex_encoding']
else:
self._use_binary_hex_encoding = False

json.JSONDecoder.__init__(self, *args, **kwargs)

def _parse_string(*args, **kwargs):
s, idx = scanstring(*args, **kwargs)
if self._use_binary_hex_encoding:
if s and s[0:2] == '0x':
s = a2b_hex(s[2:])
else:
if s and s[0] == '\x00':
s = base64.b64decode(s[1:])
return s, idx

self.parse_string = _parse_string

# we need to recreate the internal scan function ..
Expand All @@ -375,14 +398,17 @@ def __init__(self, *args, **kwargs):
# not the C version, as the latter won't work
# self.scan_once = scanner.make_scanner(self)

def _loads(s):
return json.loads(s, cls=_WAMPJsonDecoder)
def _loads(s, use_binary_hex_encoding=False):
return json.loads(s,
use_binary_hex_encoding=use_binary_hex_encoding,
cls=_WAMPJsonDecoder)

def _dumps(obj):
def _dumps(obj, use_binary_hex_encoding=False):
return json.dumps(obj,
separators=(',', ':'),
ensure_ascii=False,
sort_keys=False,
use_binary_hex_encoding=use_binary_hex_encoding,
cls=_WAMPJsonEncoder)

_json = json
Expand All @@ -399,20 +425,20 @@ class JsonObjectSerializer(object):

BINARY = False

def __init__(self, batched=False):
def __init__(self, batched=False, use_binary_hex_encoding=False):
"""
Ctor.
:param batched: Flag that controls whether serializer operates in batched mode.
:type batched: bool
"""
self._batched = batched
self._use_binary_hex_encoding = use_binary_hex_encoding

def serialize(self, obj):
"""
Implements :func:`autobahn.wamp.interfaces.IObjectSerializer.serialize`
"""
s = _dumps(obj)
s = _dumps(obj, use_binary_hex_encoding=self._use_binary_hex_encoding)
if isinstance(s, str):
s = s.encode('utf8')
if self._batched:
Expand All @@ -430,7 +456,7 @@ def unserialize(self, payload):
chunks = [payload]
if len(chunks) == 0:
raise Exception("batch format error")
return [_loads(data.decode('utf8')) for data in chunks]
return [_loads(data.decode('utf8'), use_binary_hex_encoding=self._use_binary_hex_encoding) for data in chunks]


IObjectSerializer.register(JsonObjectSerializer)
Expand Down
1 change: 1 addition & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Changelog
21.2.2
------

* new: use_binary_hex_encoding option for JSON object serializer
* fix: correct some sphinx doc references
* new: minimum supported Python (language) version is now 3.7 (on CPython and PyPy)
* new: more XBR proxy/stub code generation capabilities (RPC call/invoation handlers)
Expand Down

0 comments on commit 9ca21af

Please sign in to comment.