3

我为 jsonpickle 编写了一个自定义处理程序,以便在序列化对象容器之前转换枚举值。

import jsonpickle
from enum import Enum


class Bar(Enum):
    A = 1
    B = 2


class Foo:
    def __init__(self):
        self.hello = 'hello'
        self.bar = [Bar.A, Bar.B]


class Handler(jsonpickle.handlers.BaseHandler):

    def flatten(self, obj, data):  # data contains {}
        print(obj)

        ### How should I handle the enum? ###

        return data


jsonpickle.handlers.registry.register(Bar, Handler)


def main():
    fizbuz = Foo()
    encoded = jsonpickle.encode(fizbuz)
    print(encoded)


if __name__ == '__main__':
    main()

处理程序是用包含枚举值的 obj 调用的。但是数据字典已经包含一个键值对,所以我不能只返回一个表示枚举的值。

所以我的问题是,当我自定义处理返回一个唯一值的元素时,我需要添加到数据字典中的关键值对应该是什么,而我需要将其放入预先填充的数据字典中稍后重建对象所需的反射数据。

4

1 回答 1

1

我不明白你为什么担心提供的字典?这是您用来帮助处理程序代码的输入,如果您不想要它,则根本不需要使用它。正如您所指出的,如果您使用没有 unpicklable=False 的编码,则它不是 {}。如果你不包括它,那么你实际上会得到这个:

{'py/object': '__main__.Bar'}

所提供的只是变量的类型,并且您编写了处理程序,因此您自然知道类型。

如果您想要一个漂亮的枚举 JSON 输出,只需告诉 Python flatten 函数的 obj 是 Bar 类型(可选,但对 IDE 和以后的维护很好),如下所示:

def flatten(self, obj: Bar, data):

然后,只需返回 obj.name。这样做,输出是:

{"py/object": "__main__.Foo", "bar": ["A", "B"], "hello": "hello"}

当然,我们可以通过告诉编码器不要担心以后解码来使其更清晰:

unpicklable=False

那么最终的输出是:

{"bar": ["A", "B"], "hello": "hello"}

整个示例代码:

import jsonpickle
from enum import Enum


class Bar(Enum):
    A = 1
    B = 2


class Foo:
    def __init__(self):
        self.hello = 'hello'
        self.bar = [Bar.A, Bar.B]


class Handler(jsonpickle.handlers.BaseHandler):

    def flatten(self, obj: Bar, data):
        print(obj)

        return obj.name


jsonpickle.handlers.registry.register(Bar, Handler)


def main():
    fizbuz = Foo()
    encoded = jsonpickle.encode(fizbuz, unpicklable=False)
    print(encoded)


if __name__ == '__main__':
    main()

通用方法

您还可以通过使用这样的类来处理所有枚举:

from enum import Enum

import jsonpickle


class JsonEnumHandler(jsonpickle.handlers.BaseHandler):

    def restore(self, obj):
        pass

    def flatten(self, obj: Enum, data):
        return obj.name

然后,像这样在 JSON 中注册每个枚举:

    jsonpickle.handlers.registry.register(LimitType, JsonEnumHandler)
    jsonpickle.handlers.registry.register(DeviceType, JsonEnumHandler)
于 2018-11-14T01:52:13.617 回答