首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有jsonpickle的泡菜(Python 3.7)

带有jsonpickle的泡菜(Python 3.7)
EN

Stack Overflow用户
提问于 2019-12-15 02:07:21
回答 1查看 907关注 0票数 2

我对使用jsonpickle有一个问题。相反,我相信它工作正常,但它没有产生我想要的输出。

我有一个叫'Node‘的类。在'Node‘中有四个In (x,y,width,height)和一个叫做'NodeText’的StringVar。

序列化StringVar的问题是,其中有很多信息,对我来说,这是不必要的。我在程序运行时使用它,但不需要保存和加载它。

因此,我使用了一种方法来更改jsonpickle保存的内容,对我的节点使用__getstate__方法。这样我就可以这样做了:

代码语言:javascript
复制
    def __getstate__(self):
        state = self.__dict__.copy()
        del state['NodeText']
        return state

到目前为止,这个方法工作得很好,并且没有保存NodeText。问题来的太多了。我像往常一样将文件加载到一个对象(在本例中是一个节点列表)。

加载的问题是:从json加载的项不是我的类中定义的节点。它们几乎是一样的(它们有x、y、width和height),但是因为NodeText没有保存在json文件中,所以这些类似Node的对象没有这个属性。当我在屏幕上创建这些节点的可视实例时,这会导致错误,因为StringVar用于tkinter Entry文本变量。

我想知道是否有办法将这个“几乎节点”加载到我的实际节点中。我可以一次只复制一个属性到一个新的实例中,但这似乎不是一个好方法。

我还可以在保存之前将NodeText StringVar设为空(从而节省了文件中的空间),然后在加载时重新初始化它。这意味着我将拥有完整的对象,但不知何故,这似乎是一个笨拙的变通方法。

如果您想知道StringVar还有多少信息,我的测试json文件只有两个节点。仅保存基本属性(x,y,width,height),文件大小为1k。每个都有一个StringVar,就变成了8k。在小幅增长的情况下我不会太在意,但这是相当大的。

我可以强制加载到这个Node类型,而不仅仅是Python创建的某个新类型吗?

编辑:如果你想知道json是什么样子的,看看这里:

代码语言:javascript
复制
{
  "1": {
    "py/object": "Node.Node",
    "py/state": {
      "ImageLocation": "",
      "TextBackup": "",
      "height": 200,
      "uID": 1,
      "width": 200,
      "xPos": 150,
      "yPos": 150
    }
  },
  "2": {
    "py/object": "Node.Node",
    "py/state": {
      "ImageLocation": "",
      "TextBackup": "",
      "height": 200,
      "uID": 2,
      "width": 100,
      "xPos": 50,
      "yPos": 450
    }
  }
}

因为有类名,所以我认为它应该是类的实例化。但是当您使用jsonpickle加载文件时,您将获得字典,并且可以检查加载的数据并检查每个节点。这两个节点都不包含属性“NodeText”。也就是说,它不是值为“None”的东西--属性simple不在那里。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-17 08:05:05

这是因为jsonpickle通常不知道对象中有哪些字段,它只恢复从状态传递的字段,但状态不会恢复NodeText属性。所以它只是错过了它:)

您可以添加一个__setstate__魔术方法来在还原的对象中实现该属性。这样,您将能够处理有或没有该属性的转储。

代码语言:javascript
复制
    def __setstate__(self, state):
        state.setdefault('NodeText', None)

        for k, v in state.items():
            setattr(self, k, v)

一个小例子

代码语言:javascript
复制
from pprint import pprint, pformat

import jsonpickle


class Node:
    def __init__(self) -> None:
        super().__init__()

        self.NodeText = Node
        self.ImageLocation = None
        self.TextBackup = None
        self.height = None
        self.uID = None
        self.width = None
        self.xPos = None
        self.yPos = None

    def __setstate__(self, state):
        state.setdefault('NodeText', None)

        for k, v in state.items():
            setattr(self, k, v)

    def __getstate__(self):
        state = self.__dict__.copy()

        del state['NodeText']
        return state

    def __repr__(self) -> str:
        return str(self.__dict__)


obj1 = Node()
obj1.NodeText = 'Some heavy description text'
obj1.ImageLocation = 'test ImageLocation'
obj1.TextBackup = 'test TextBackup'
obj1.height = 200
obj1.uID = 1
obj1.width = 200
obj1.xPos = 150
obj1.yPos = 150

print('Dumping ...')
dumped = jsonpickle.encode({1: obj1})
print(dumped)

print('Restoring object ...')
print(jsonpickle.decode(dumped))

输出

代码语言:javascript
复制
# > python test.py
Dumping ...
{"1": {"py/object": "__main__.Node", "py/state": {"ImageLocation": "test ImageLocation", "TextBackup": "test TextBackup", "height": 200, "uID": 1, "width": 200, "xPos": 150, "yPos": 150}}}
Restoring object ...
{'1': {'ImageLocation': 'test ImageLocation', 'TextBackup': 'test TextBackup', 'height': 200, 'uID': 1, 'width': 200, 'xPos': 150, 'yPos': 150, 'NodeText': None}}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59337797

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档