Gurkenkönig
Gurkenkönig

Reputation: 828

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))

Upvotes: 3

Views: 3086

Answers (2)

André C. Andersen
André C. Andersen

Reputation: 9405

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.

Upvotes: 1

Gurkenkönig
Gurkenkönig

Reputation: 828

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())

Upvotes: 3

Related Questions