【问题标题】:How to deal with a single value when implementing jsonpickle custom handlers?实现 jsonpickle 自定义处理程序时如何处理单个值?
【发布时间】:2018-04-22 06:47:11
【问题描述】:

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

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

【问题讨论】:

    标签: python json python-3.x jsonpickle


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 2011-05-04
      • 2021-08-10
      • 1970-01-01
      • 2010-11-08
      • 1970-01-01
      • 2014-12-22
      • 2012-09-30
      • 2020-09-26
      • 2012-09-10
      相关资源
      最近更新 更多