Reputation: 19329
Both the Child
and Parent
classes inherit from Python dictionary:
import json
class Child(dict):
def __init__(self, **kwargs):
super(Child, self).__init__(**kwargs)
class Parent(dict):
def __init__(self, **kwargs):
super(Parent, self).__init__(**kwargs)
parent = Parent(child = Child())
print type(parent['child'])
prints:
<class '__main__.Child'>
After performing the serialization and de-serialization using json.dumps
and json.loads
the Parent['child']
becomes a regular dictionary:
dumped = json.dumps(parent)
loaded = json.loads(dumped)
parent_2 = Parent(**loaded)
print type(parent_2['child'])
prints:
<type 'dict'>
Question: how to make sure that after the serialization, the parent_2['child']
is the instance of the Child
and not a regular Python dictionary?
Upvotes: 1
Views: 281
Reputation: 15568
You could use pickle. It can be dangerous to unpickle unknown pickled objects(as they can be malicious).
read documentation https://docs.python.org/3/library/pickle.html as it contains more information.
import pickle
class Foo:
attr = 'A class attribute'
with open('pickle_class.pk','wb') as f:
pickle.dump(Foo,f)
# we open the file for reading
with open('pickle_class.pk','rb') as f:
Bar = pickle.load(f)
# Test if they are the same.
assert Bar==Foo,'Not the Same'
You can also compress.
import bz2
import pickle
with bz2.BZ2File('pickled_class', 'wb') as f:
pickle.dump(Foo, s)
In some cases, as using multithreading and lambda, dill, third-party module, can be handy as pickle throws
PicklingError: Can't pickle <function <lambda> at 0x111d0a7b8>: attribute lookup <lambda> on __main__ failed
The flow and danger(unpickling malicious software) are the same:
import dill
class Foo:
attr = 'A class attribute'
with open('pickle_class.pk','wb') as f:
dill.dump(Foo,f)
Read dill documentation: https://pypi.org/project/dill/
N.B: Never-ever load unknown pickled file
Upvotes: 1
Reputation: 3313
There is a package called jsonpickle. It seems to do the trick;
import json
import jsonpickle
class Child(dict):
def __init__(self, **kwargs):
super(Child, self).__init__(**kwargs)
class Parent(dict):
def __init__(self, **kwargs):
super(Parent, self).__init__(**kwargs)
if __name__ == '__main__':
parent = Parent(child=Child())
dumped = jsonpickle.encode(parent)
loaded = jsonpickle.decode(dumped)
parent_2 = Parent(**loaded)
print(type(parent_2['child']))
<class '__main__.Child'>
Note; for this to work, the Json will have information about the original object graph so that it can be restored.
('{"py/object": "__main__.Parent", "child": {"py/object": "__main__.Child", '
'"__dict__": {}}, "__dict__": {}}')
Upvotes: 0
Reputation: 4265
loads
makes a dictionary and that's that. After some trial and error I found it out. (Note: It looks like you are using legacy Python so the syntax may need some tweaking from this solution.)
import json
class Child(dict):
def __init__(self, **kwargs):
super(Child, self).__init__(**kwargs)
class Parent(dict):
def __init__(self, **kwargs):
super(Parent, self).__init__(**kwargs)
parent = Parent(child=Child())
print(type(parent['child']))
if __name__ == '__main__':
dumped = json.dumps(parent)
loaded = json.loads(dumped)
parent_2 = Parent(child=Child(**loaded)) # Changed how you call Parent
print(type(parent_2['child']))
Without calling the args of Parent
with a dict
initialized as Child
, we can have no expectation of detecting the Child
type unless you add additional logic to detect the type.
Upvotes: 2