diff options
Diffstat (limited to 'g_sorcery/serialization.py')
-rw-r--r-- | g_sorcery/serialization.py | 98 |
1 files changed, 78 insertions, 20 deletions
diff --git a/g_sorcery/serialization.py b/g_sorcery/serialization.py index e051596..780de6f 100644 --- a/g_sorcery/serialization.py +++ b/g_sorcery/serialization.py @@ -4,38 +4,100 @@ """ serialization.py ~~~~~~~~~~~~~~~~ - + json serialization - - :copyright: (c) 2013 by Jauhien Piatlicki + + :copyright: (c) 2013-2015 by Jauhien Piatlicki :license: GPL-2, see LICENSE for more details. """ import json import importlib +from .exceptions import SerializationError + +def step_to_raw_serializable(obj): + """ + Make one step of convertion of object + to the type that is serializable + by the json library. + + None return value signifies an error. + """ + if hasattr(obj, "serialize"): + if hasattr(obj, "deserialize"): + module = obj.__class__.__module__ + name = obj.__class__.__name__ + value = obj.serialize() + return {"python_module" : module, + "python_class" : name, + "value" : value} + else: + return obj.serialize() + return None + + +def to_raw_serializable(obj): + """ + Convert object to the raw serializable type. + Logic is the same as in the standard json encoder. + """ + if isinstance(obj, str) \ + or obj is None \ + or obj is True \ + or obj is False \ + or isinstance(obj, int) \ + or isinstance(obj, float) \ + or isinstance(obj, (list, tuple)) \ + or isinstance(obj, dict): + return obj + else: + sobj = step_to_raw_serializable(obj) + if not sobj: + raise SerializationError('Non serializable object: ', sobj) + return to_raw_serializable(sobj) + + +def step_from_raw_serializable(sobj): + """ + Make one step of building of object from the + raw json serializable type. + """ + if "python_class" in sobj: + module = importlib.import_module(sobj["python_module"]) + cls = getattr(module, sobj["python_class"]) + return cls.deserialize(sobj["value"]) + return sobj + + +def from_raw_serializable(sobj): + """ + Build object from the raw serializable object. + """ + if isinstance(sobj, dict): + res = {k: from_raw_serializable(v) for k, v in sobj.items()} + return step_from_raw_serializable(res) + elif isinstance(sobj, list): + return [from_raw_serializable(item) for item in sobj] + else: + return sobj + class JSONSerializer(json.JSONEncoder): """ Custom JSON encoder. Each serializable class should have a method serialize - that returns JSON serializable value. If class addfitionally + that returns JSON serializable value. If class additionally has a classmethod deserialize that it can be deserialized and additional metainformation is added to the resulting JSON. """ def default(self, obj): - if hasattr(obj, "serialize"): - if hasattr(obj, "deserialize"): - module = obj.__class__.__module__ - name = obj.__class__.__name__ - value = obj.serialize() - return {"python_module" : module, - "python_class" : name, - "value" : value} - else: - return obj.serialize() - return json.JSONEncoder.default(self, obj) + res = step_to_raw_serializable(obj) + if res: + return res + else: + return json.JSONEncoder.default(self, obj) def deserializeHook(json_object): @@ -46,8 +108,4 @@ def deserializeHook(json_object): that takes value (previously returned by serialize method) and transforms it into class instance. """ - if "python_class" in json_object: - module = importlib.import_module(json_object["python_module"]) - cls = getattr(module, json_object["python_class"]) - return cls.deserialize(json_object["value"]) - return json_object + return step_from_raw_serializable(json_object) |