Python JSON序列化排除某些字段

标签 python json serialization

摘要

我有一个 Python 对象层次结构,我想使用 JSON 进行序列化(仅通过 https://docs.python.org/3/library/json.html ,不使用任何额外的第三方库)。我想排除某些字段/属性/子对象。我发现很难找到一个关于如何实现这一目标的简单答案?

示例

我将有一个派生类实例,结果如下:

class MyItemClass(BaseItemClass):
    self.saveThisProperty = 999
    self.dontSaveThisProperty = "Something"
    self.saveThisObject = ObjectType1()
    self.dontSaveThisObject = ObjectType2()

如果我要序列化为 XML,我希望它看起来像
<MyItemClass>
    <saveThisProperty>999</saveThisProperty>
    <saveThisObject>
        ...
    </saveThisObject>
</MyItemClass>

请注意,我只序列化了某些属性/子对象,我不想序列化整个 BaseItemClass我的类实例是从中派生的。

在 XML 中我很好。我知道如何按照我想要的方式输出一些 XML,或者输出到我在最后保存的临时内存文档,或者通过增量输出单个节点/元素到流。我不必序列化所有内容。例如。
xmlStream.writeStartElement("MyItemClass")
    xmlStream.writeElementWithValue("saveThisProperty", 999)
    xmlStream.writeStartElement("saveThisObject")
        ...
    xmlStream.writeEndElement("saveThisObject")
xmlStream.writeEndElement("MyItemClass")

对于 JSON,我不能这样做,对吗?我是否必须通过仅将我想要的属性/子对象复制到其中然后 JSON 序列化来创建一些新的“独立”对象层次结构(不从 BaseClass 派生)?

我确实看到有 json.dump(default = ...) ,但它说:

If specified, default should be a function that gets called for objects that can’t otherwise be serialized. It should return a JSON encodable version of the object



然而,并不是原始对象不能被默认 Python->JSON 序列化,而是我不想要那种默认的、序列化的所有行为,我想要我的“选择性”行为。

最佳答案

我是 OP。为了清楚起见,我在这里发布了我最终用于我的案例的内容。

我已将@Sina Rezaei 在此线程中的帖子标记为已接受的解决方案,因为那(他帖子的最后一部分)和@snakechamerb 的评论启发了我了解需要什么。

我的解决方案的轮廓看起来像:

class ModelScene(QGraphicsScene):

  # Serialize whole scene to JSON into stream
  def json_serialize(self, stream) -> None:
    # Get `json.dump()` to call `ModelScene.json_serialize_dump_obj()` on every object to be serialized
    json.dump(self, stream, indent=4, default=ModelScene.json_serialize_dump_obj)

  # Static method to be called from `json.dump(default=ModelScene.json_serialize_dump_obj)`
  # This method is called on every object to be dumped/serialized
  @staticmethod
  def json_serialize_dump_obj(obj):
    # if object has a `json_dump_obj()` method call that...
    if hasattr(obj, "json_dump_obj"):
      return obj.json_dump_obj()
    # ...else just allow the default JSON serialization
    return obj

  # Return dict object suitable for serialization via JSON.dump()
  # This one is in `ModelScene(QGraphicsScene)` class
  def json_dump_obj(self) -> dict:
    return {
      "_classname_": self.__class__.__name__,
      "node_data": self.node_data
      }

class CanvasModelData(QAbstractListModel):

  # Return dict object suitable for serialization via JSON.dump()
  # This one is class CanvasModelData(QAbstractListModel)
  def json_dump_obj(self) -> dict:
    _data = {}
    for key, value in self._data.items():
      _data[key] = value
    return {
      "_classname_": self.__class__.__name__,
      "data_type": self.data_type,
      "_data": _data
      }
  • 每个“复杂”类定义了一个 def json_dump_obj(self) -> dict:方法。
  • 该方法仅返回序列化中所需的属性/子对象。
  • 顶级json.dump(self, stream, default=ModelScene.json_serialize_dump_obj)通过静态方法 ModelScene.json_serialize_dump_obj 导致每个访问的节点被增量序列化为流.这叫我的 obj.json_dump_obj()如果可用,否则为基本对象类型的默认 JSON 序列化。

  • 有趣的是,我遇到了一个和我有同样担忧的人。来自 python中的json.dump()和json.dumps()有什么区别? , 解决方案 https://stackoverflow.com/a/57087055/489865 :

    In memory usage and speed.

    When you call jsonstr = json.dumps(mydata) it first creates a full copy of your data in memory and only then you file.write(jsonstr) it to disk. So this is a faster method but can be a problem if you have a big piece of data to save.

    When you call json.dump(mydata, file) -- without 's', new memory is not used, as the data is dumped by chunks. But the whole process is about 2 times slower.

    Source: I checked the source code of json.dump() and json.dumps() and also tested both the variants measuring the time with time.time() and watching the memory usage in htop.

    关于Python JSON序列化排除某些字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59103160/

    相关文章:

    javascript - 在javascript中读取json字符串

    java - 找不到符号 ois

    .net - Protocol Buffer : Should I use int64 or fixed64 to represent a . NET DateTime 值?

    python - 如何在 Django 中使用模型进行查询

    python - celery Pyramid 周期性任务

    python - 与手写 C 相比,pypy 是否可以快速处理线程和套接字?

    python - 在 Django 模板中,当键存储在变量中时,如何打印字典中的值?

    json - 使用 curl 模拟 github 服务 Hook

    php - 如何使用php将mysql数据库表数据转换成json

    json - 使用C#中的嵌套字符串表示json数据的反序列化模型