Skip to content

Commit

Permalink
make all typed dicts json (de)serializable
Browse files Browse the repository at this point in the history
  • Loading branch information
andre-merzky committed Apr 5, 2024
1 parent 1e686e6 commit 571d00b
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 7 deletions.
33 changes: 27 additions & 6 deletions src/radical/utils/serialize.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

import copy
import json
import msgpack

Expand All @@ -16,7 +17,7 @@ def __init__(self, ctype, encode, decode):

# ------------------------------------------------------------------------------
#
def register_serializable(cls, encode, decode):
def register_serializable(cls, encode=None, decode=None):
'''
register a class for json and msgpack serialization / deserialization.
Expand All @@ -26,21 +27,36 @@ def register_serializable(cls, encode, decode):
decode (callable): recreates the class instance from that data structure
'''

if encode is None: encode = cls
if decode is None: decode = cls

global _ctypes
_ctypes[cls.__name__] = _CType(cls, encode, decode)


# ------------------------------------------------------------------------------
#

class _json_encoder(json.JSONEncoder):
'''
internal methods to encode registered classes to json
'''

def encode(self, o, *args, **kw):

from .typeddict import TypedDict
if isinstance(o, TypedDict):
# print('TypedDict: %s' % type(o).__name__)
o = copy.deepcopy(o)
o['_xtype'] = type(o).__name__
return super().encode(o, *args, **kw)

def default(self, obj):
# print('encode: %s' % obj)
for cname,methods in _ctypes.items():
if isinstance(obj, methods.ctype):
return {'__%s__' % cname: True,
'as_str' : methods.encode(obj)}
return {'_xtype': cname,
'as_str': methods.encode(obj)}
return super().default(obj)

# ------------------------------------------------------------------------------
Expand All @@ -49,10 +65,15 @@ def _json_decoder(obj):
'''
internal methods to decode registered classes from json
'''
# print('decode: %s' % obj)
for cname, methods in _ctypes.items():
if '__%s__' % cname in obj:
print('found %s' % cname)
return methods.decode(obj['as_str'])
# print('check %s' % cname)
if '_xtype' in obj and obj['_xtype'] == cname:
del obj['_xtype']
# print('found %s' % cname)
if 'as_str' in obj:
return methods.decode(obj['as_str'])
return methods.decode(obj)
return obj


Expand Down
5 changes: 4 additions & 1 deletion src/radical/utils/typeddict.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
import copy
import sys

from .misc import as_list, as_tuple, is_string
from .serialize import register_serializable
from .misc import as_list, as_tuple, is_string


# ------------------------------------------------------------------------------
Expand Down Expand Up @@ -138,6 +139,8 @@ def __init__(self, from_dict=None, **kwargs):
`kwargs`).
'''

register_serializable(self.__class__)

self.update(copy.deepcopy(self._defaults))
self.update(from_dict)

Expand Down

0 comments on commit 571d00b

Please sign in to comment.