在Python3中将嵌套对象保存到文件

时间:2018-08-12 13:15:59

标签: json python-3.x

如何将Python对象的这种结构保存到文件(最好是JSON)中?以及如何从文件中再次加载此结构?

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

2 个答案:

答案 0 :(得分:1)

由于提到了“棘手”,我找到了一个很好的工作非常简单的解决方案来保存对象数组:

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

答案 1 :(得分:1)

如果您不希望泡菜,也不想使用外部库,则总是可以用困难的方式做到这一点:

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)

不必使用setattr()动态地将属性分配给类,也可以手动进行。

这样做可能有很多陷阱,所以要小心。