1

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?

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

1 Comment

Clean and convenient use of pickle with appropriate warning -- I think this solution is better than mine but I will leave mine up for reference.
0

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__": {}}')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.