Skip to content

Commit

Permalink
implement custom (de)serialization for json and msgpack
Browse files Browse the repository at this point in the history
  • Loading branch information
andre-merzky committed Apr 5, 2024
1 parent efac08a commit 752a5e6
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/radical/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,14 @@

from .json_io import read_json, read_json_str, write_json
from .json_io import parse_json, parse_json_str, metric_expand
from .json_io import register_json_class, dumps_json
from .which import which
from .tracer import trace, untrace
from .get_version import get_version

from .serialize import to_json, from_json, to_msgpack, from_msgpack
from .serialize import register_serialization


# import various utility methods
from .ids import *
Expand Down
32 changes: 31 additions & 1 deletion src/radical/utils/json_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,23 @@
from .misc import as_string, ru_open


_json_classes = dict()

def register_json_class(cls, check, convert):

global _json_classes
_json_classes[cls.__name__] = [check, convert]


class _json_encoder(json.JSONEncoder):

def default(self, o):
for cls, (check, convert) in _json_classes.items():
if check(o):
return convert(o)
return super().default(o)


# ------------------------------------------------------------------------------
#
def read_json(fname, filter_comments=True):
Expand Down Expand Up @@ -61,11 +78,24 @@ def write_json(data, fname):
fname = tmp

with ru_open(fname, 'w') as f:
json.dump(data, f, sort_keys=True, indent=4, ensure_ascii=False)
json.dump(data, f, sort_keys=True, indent=4, ensure_ascii=False,
cls=_json_encoder)
f.write('\n')
f.flush()


# ------------------------------------------------------------------------------
#
def dumps_json(data):
'''
thin wrapper around python's json write, for consistency of interface
'''

return json.dumps(data, sort_keys=True, indent=4, ensure_ascii=False,
cls=_json_encoder)


# ------------------------------------------------------------------------------
#
def parse_json(json_str, filter_comments=True):
Expand Down
2 changes: 2 additions & 0 deletions src/radical/utils/zmq/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import zmq
import errno

import msgpack

from ..url import Url
from ..misc import as_list
from ..misc import ru_open
Expand Down
56 changes: 56 additions & 0 deletions tests/unittests/test_serialization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env python3

__author__ = "Radical.Utils Development Team (Andre Merzky)"
__copyright__ = "Copyright 2024, RADICAL@Rutgers"
__license__ = "MIT"

import os

import radical.utils as ru


# ------------------------------------------------------------------------------
#
def test_serialization():

class Complex(object):

def __init__(self, real, imag):
self.real = real
self.imag = imag

def __eq__(self, other):
return self.real == other.real and self.imag == other.imag

def serialize(self):
return {'real': self.real, 'imag': self.imag}

@classmethod
def deserialize(cls, data):
return cls(data['real'], data['imag'])


ru.register_serialization(Complex, encode=Complex.serialize,
decode=Complex.deserialize)

data = {'foo': {'complex_number': Complex(1, 2)}}
json_str = ru.to_json(data)
new_data = ru.from_json(json_str)

assert data == new_data

msgpack_str = ru.to_msgpack(data)
new_data = ru.from_msgpack(msgpack_str)

assert data == new_data


# ------------------------------------------------------------------------------
#
if __name__ == '__main__':

test_serialization()


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

0 comments on commit 752a5e6

Please sign in to comment.