Python JSON序列化排除某些字段

乔恩勇敢

概括

我有一个 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,我不能这样做,对吗?是否必须BaseClass通过将我想要的属性/子对象复制到其中然后 JSON 序列化创建一些新的“独立”对象层次结构(没有派生自)?

我确实看到有json.dump(default = ...),但上面写着:

如果指定,则 default 应该是一个函数,该函数为无法以其他方式序列化的对象调用。它应该返回对象的 JSON 可编码版本

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

新浪瑞泽

针对您的情况,我可以想到三种解决方案:

解决方案一:使用Pykson第三方库,将你想要序列化的字段定义为pykson字段。

样本:

class MyItemClass(pykson.JsonObject):
    saved_property = pykson.IntegerField()

my_object = MyItemClass(saved_property=1, accept_unknown=True)
my_object.unsaved_property = 2
pykson.Pykson().to_json(my_object)

免责声明:我是 pykson 库的开发人员。

解决方案 2:第二种解决方案是使用带有自定义默认解串器的包装类。

class ObjectWrapper:
    def __init__(self, value, should_serialize=False)
        self.value = value
        self.should_serialize = should_serialize

def default_handler(obj):
    if isinstance(obj, ObjectWrapper):
        if obj.should_serialize:
            return obj.value
        else:
            return None
    else:
        raise TypeError

json.dump(default=default_handler)

解决方案 3:这可能是一个坏主意,但是如果您有一个很深的层次结构,您还可以向将被序列化的 allc 类添加一个函数,并使用此函数获取字典并轻松将字典转换为 json。

class MyChildClass:
     def __init__(self, serialized_property, not_serialized_property):
        self.serialized_property = serialized_property
        self.not_serialized_property = not_serialized_property

     def to_dict(self):
        # only add serialized property here
        return {
            "serialized_property": self.serialized_property
        }

class MyParentClass:
    def __init__(self, child_property, some_other_property):
        self.child_property = child_property
        self.some_other_property = some_other_property

    def to_dict(self):
        return {
            'child_property': self.child_property.to_dict(),
            'some_other_property': self.some_other_property
        }

my_child_object = MyChildClass(serialized_property=1, not_serialized_property=2)
my_parent_object = MyParentClass(child_property=my_child_object, some_other_property='some string here')
json.dumps(my_parent_object.to_dict())

或者您可以使用默认处理程序实现相同的结果:

class MyChildClass:
     def __init__(self, serialized_property, not_serialized_property):
        self.serialized_property = serialized_property
        self.not_serialized_property = not_serialized_property

     def to_dict(self):
        # only add serialized property here
        return {
            "serialized_property": self.serialized_property
        }

class MyParentClass:
    def __init__(self, child_property, some_other_property):
        self.child_property = child_property
        self.some_other_property = some_other_property

    def to_dict(self):
        return {
            'child_property': self.child_property,
            'some_other_property': self.some_other_property
        }

def handle_default(obj):
    if isinstance(obj, MyChildClass):
        return obj.to_dict()
    elif isinstance(obj, MyParentClass):
        return obj.to_dict()
    return None

my_child_object = MyChildClass(serialized_property=1, not_serialized_property=2)
my_parent_object = MyParentClass(child_property=my_child_object, some_other_property='some string here')
json.dumps(my_parent_object, default=handle_default)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章