在实现jsonpickle自定义处理程序时如何处理单个值?

时间:2018-04-22 06:47:11

标签: python json python-3.x jsonpickle

我为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调用处理程序。但是数据dict已经包含一个键值对,所以我不能只返回表示枚举的单个值。

所以我的问题是当我需要在数据字典中加入一个唯一值的自定义处理元素时,我需要添加到数据字典中的键值对应该是什么? - 使用反射数据填充,以便稍后重建对象。

1 个答案:

答案 0 :(得分:0)

我不明白您为什么担心所提供的命令?这是您用于辅助处理程序代码的输入,如果您不需要它,则根本不需要使用它。如您所指出的,如果您使用无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)