Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save Nested Objects to File in Python3

How can I save this structure of Python objects into a file (preferably JSON)? And how can I load this structure from the file again?

class Nested(object):
    def __init__(self, n):
        self.name = "Nested Object: " + str(n)
        self.state = 3.14159265359

class Nest(object):
    def __init__(self):
        self.x = 1
        self.y = 2
        self.objects = []

tree = []
tree.append(Nest())
tree.append(Nest())
tree.append(Nest())

tree[0].objects.append(Nested(1))
tree[0].objects.append(Nested(2))

tree[1].objects.append(Nested(1))


tree[2].objects.append(Nested(7))
tree[2].objects.append(Nested(8))
tree[2].objects.append(Nested(9))
like image 496
Gurkenkönig Avatar asked Dec 18 '25 14:12

Gurkenkönig


2 Answers

Thanks to the reference to "pickle" I found a well working very simple solution to save my array of objects:

pickle

import pickle

pickle.dump( tree, open( "save.p", "wb" ) )

loaded_objects = pickle.load( open( "save.p", "rb" ) )

jsonpickle

import jsonpickle

frozen = jsonpickle.encode(tree)

with open("save.json", "w") as text_file:
    print(frozen, file=text_file)

file = open("save.json", "r") 
loaded_objects = jsonpickle.decode(file.read())
like image 177
Gurkenkönig Avatar answered Dec 20 '25 09:12

Gurkenkönig


If you don't want pickle, nor want to use an external library you can always do it the hard way:

import json

class NestEncoder(json.JSONEncoder):
    def default(self, obj):
        entry = dict(obj.__dict__)
        entry['__class__'] = obj.__class__.__name__
        return entry

class NestDecoder(json.JSONDecoder):
    def __init__(self):
        json.JSONDecoder.__init__(self, object_hook=self.dict_to_object)

    def dict_to_object(self, dictionary):
        if dictionary.get("__class__") == "Nested":
            obj = Nested.__new__(Nested)
        elif dictionary.get("__class__") == "Nest":
            obj = Nest.__new__(Nest)
        else:
            return dictionary

        for key, value in dictionary.items():
            if key != '__class__':
                setattr(obj, key, value)
        return obj

with open('nest.json', 'w') as file:
    json.dump(tree, file, cls=NestEncoder)

with open('nest.json', 'r') as file:
    tree2 = json.load(file, cls=NestDecoder)

print("Smoke test:")
print(tree[0].objects[0].name)
print(tree2[0].objects[0].name)

Assigning the the attributes to the classes doesn't have to be done dynamically with setattr() you can also do it manually.

There are probably plenty of pitfalls with doing it like this, so be careful.

like image 27
André C. Andersen Avatar answered Dec 20 '25 09:12

André C. Andersen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!