1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
serialization.py
~~~~~~~~~~~~~~~~
json serialization
:copyright: (c) 2013-2015 by Jauhien Piatlicki
:license: GPL-2, see LICENSE for more details.
"""
import json
import importlib
from .compatibility import basestring
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, basestring) \
or obj is None \
or obj is True \
or obj is False \
or isinstance(obj, int) \
or isinstance(obj, float):
return obj
elif isinstance(obj, dict):
return {k: to_raw_serializable(v) for k, v in obj.items()}
elif isinstance(obj, (list, tuple)):
return [to_raw_serializable(item) for item in obj]
else:
sobj = step_to_raw_serializable(obj)
if not sobj:
raise TypeError('Non serializable object: ', obj)
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 additionally
has a classmethod deserialize that it can be deserialized
and additional metainformation is added to the resulting JSON.
"""
def default(self, obj):
res = step_to_raw_serializable(obj)
if res:
return res
else:
return json.JSONEncoder.default(self, obj)
def deserializeHook(json_object):
"""
Custom JSON decoder.
Each class that can be deserialized should have classmethod deserialize
that takes value (previously returned by serialize method) and transforms
it into class instance.
"""
return step_from_raw_serializable(json_object)
|