Skip to content

Commit 388e546

Browse files
committed
Add encoder and decoder to tuple
1 parent ac5c8be commit 388e546

File tree

4 files changed

+58
-3
lines changed

4 files changed

+58
-3
lines changed

json_tricks/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
from .encoders import TricksEncoder, json_date_time_encode, class_instance_encode, json_complex_encode, \
99
numeric_types_encode, ClassInstanceEncoder, json_set_encode, pandas_encode, nopandas_encode, \
1010
numpy_encode, NumpyEncoder, nonumpy_encode, NoNumpyEncoder, fallback_ignore_unknown, pathlib_encode, \
11-
bytes_encode, slice_encode
11+
bytes_encode, slice_encode, json_tuple_encode
1212
from .decoders import DuplicateJsonKeyException, TricksPairHook, json_date_time_hook, json_complex_hook, \
1313
numeric_types_hook, ClassInstanceHook, json_set_hook, pandas_hook, nopandas_hook, json_numpy_obj_hook, \
14-
json_nonumpy_obj_hook, pathlib_hook, json_bytes_hook
14+
json_nonumpy_obj_hook, pathlib_hook, json_bytes_hook, json_tuple_hook
1515
from .nonp import dumps, dump, loads, load
1616
from ._version import VERSION
1717

json_tricks/decoders.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ def __call__(self, dct, properties=None):
212212

213213
def json_set_hook(dct):
214214
"""
215-
Return an encoded set to it's python representation.
215+
Return an encoded set to its python representation.
216216
"""
217217
if not isinstance(dct, dict):
218218
return dct
@@ -221,6 +221,17 @@ def json_set_hook(dct):
221221
return set((tuple(item) if isinstance(item, list) else item) for item in dct['__set__'])
222222

223223

224+
def json_tuple_hook(dct):
225+
"""
226+
Return an encoded tuple to its python representation.
227+
"""
228+
if not isinstance(dct, dict):
229+
return dct
230+
if '__tuple__' not in dct:
231+
return dct
232+
return tuple(dct['__tuple__'])
233+
234+
224235
def pandas_hook(dct):
225236
if not isinstance(dct, dict):
226237
return dct

json_tricks/encoders.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,21 @@ def json_set_encode(obj, primitives=False):
331331
return obj
332332

333333

334+
def json_tuple_encode(obj, primitives=False):
335+
"""
336+
Encode python tuple as dictionary with key __tuple__ and a list of the values. Preserve order.
337+
"""
338+
print('is tuple?') #TODO @mark: TEMPORARY! REMOVE THIS!
339+
if isinstance(obj, tuple):
340+
print('is tuple!') #TODO @mark: TEMPORARY! REMOVE THIS!
341+
repr = list(obj)
342+
if primitives:
343+
return repr
344+
else:
345+
return hashodict(__tuple__=repr)
346+
return obj
347+
348+
334349
def pandas_encode(obj, primitives=False):
335350
from pandas import DataFrame, Series
336351
if isinstance(obj, DataFrame):

tests/test_bare.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from _pytest.recwarn import warns
1616
from pytest import raises, fail
1717

18+
from json_tricks.decoders import json_tuple_hook
19+
from json_tricks.encoders import json_tuple_encode
1820
from json_tricks import fallback_ignore_unknown, DuplicateJsonKeyException
1921
from json_tricks.nonp import strip_comments, dump, dumps, load, loads, \
2022
ENCODING
@@ -443,6 +445,33 @@ def test_set():
443445
assert setdata[0]['set'] == set(tuple(q) if isinstance(q, list) else q for q in back[0]['set'])
444446

445447

448+
def test_tuple():
449+
# tuple preserving behaviour is opt-in
450+
def assert_values_eq(left, right, *, as_list):
451+
assert len(left) == len(right) == 1
452+
assert len(left[0]) == len(right[0]) == 1
453+
ltup, rtup = left[0]['tup'], right[0]['tup']
454+
for i in range(len(left[0]['tup'])):
455+
if as_list and (isinstance(ltup[i], list) or isinstance(rtup[i], list)):
456+
assert list(ltup[i]) == list(rtup[i])
457+
else:
458+
assert ltup[i] == rtup[i]
459+
460+
tupledata = [{'tup': (3, exp(1), (-5, +7), False,)}]
461+
json = dumps(tupledata, extra_obj_encoders=())
462+
back = loads(json, extra_obj_pairs_hooks=())
463+
assert isinstance(back[0]['tup'], list)
464+
assert_values_eq(tupledata, back, as_list=True)
465+
json = dumps(tupledata, extra_obj_encoders=(json_tuple_encode,))
466+
back = loads(json, extra_obj_pairs_hooks=(json_tuple_hook,))
467+
assert isinstance(back[0]['tup'], tuple)
468+
assert_values_eq(tupledata, back, as_list=True)
469+
json = dumps(tupledata, extra_obj_encoders=(json_tuple_encode,), primitives=True)
470+
back = loads(json, extra_obj_pairs_hooks=(json_tuple_hook,))
471+
assert isinstance(back[0]['tup'], list)
472+
assert_values_eq(tupledata, back, as_list=True)
473+
474+
446475
def test_special_nr_parsing():
447476
nr_li_json = '[1, 3.14]'
448477
res = loads(nr_li_json,

0 commit comments

Comments
 (0)