3

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))
7
  • Saving structured data with JSON and the json module documentation from the Python docs will tell you all you need to know. Commented Aug 12, 2018 at 13:20
  • 1
    top answer shows how to do it with json and with pickle stackoverflow.com/questions/36965507/… , in my opinion if you only ever load and save this data in python pickle is superior since it keeps the exact types whereas json can only work with primitives Commented Aug 12, 2018 at 13:22
  • Possible duplicate of Save objects into JSON or XML file in Python Commented Aug 12, 2018 at 13:26
  • @AntiMatterDynamite JSON can only work with primitives out-of-the-box, but you can always write your own JSONEncoder and JSONDecoder. Commented Aug 12, 2018 at 20:44
  • 1
    Do you looking for a nested objective-Json? maybe this link helps you up. Commented Aug 12, 2018 at 21:00

2 Answers 2

3

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())
Sign up to request clarification or add additional context in comments.

Comments

1

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.

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.