将枚举成员序列化为 JSON [英] Serialising an Enum member to JSON

查看:33
本文介绍了将枚举成员序列化为 JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将 Python Enum 成员序列化为 JSON,以便我可以将生成的 JSON 反序列化回 Python 对象?

例如这段代码:

from enum import Enum导入json类状态(枚举):成功 = 0json.dumps(Status.success)

导致错误:

TypeError: 不是 JSON 可序列化的

我怎样才能避免这种情况?

解决方案

如果你想将任意 enum.Enum 成员编码为 JSON 然后解码它作为相同的枚举成员(而不是简单的枚举成员的 value 属性),您可以通过编写自定义 JSONEncoder 类,以及作为 object_hook 参数传递给 json.load()json.loads():

PUBLIC_ENUMS = {'状态':状态,# ...}类枚举编码器(json.JSONEncoder):定义默认(自我,对象):如果在 PUBLIC_ENUMS.values() 中有 type(obj):返回 {__enum__":str(obj)}返回 json.JSONEncoder.default(self, obj)def as_enum(d):如果__enum__"在 d:名称,成员 = d[__enum__"].split(.")返回 getattr(PUBLIC_ENUMS[name], member)别的:返回

as_enum 函数依赖于使用 EnumEncoder 编码的 JSON,或者与它行为相同的东西.

PUBLIC_ENUMS 成员的限制是必要的,以避免恶意制作的文本被用来欺骗调用代码以将私人信息(例如应用程序使用的密钥)保存到不相关的数据库字段,从那里它可以被暴露(见 https://chat.stackoverflow.com/transcript/message/35999686#35999686).

示例用法:

<预><代码>>>>数据 = {...动作":frobnicate",...状态":Status.success... }>>>text = json.dumps(data, cls=EnumEncoder)>>>文本'{"status": {"__enum__": "Status.success"}, "action": "frobnicate"}'>>>json.loads(文本,object_hook=as_enum){'status': <Status.success: 0>, 'action': 'frobnicate'}

How do I serialise a Python Enum member to JSON, so that I can deserialise the resulting JSON back into a Python object?

For example, this code:

from enum import Enum    
import json

class Status(Enum):
    success = 0

json.dumps(Status.success)

results in the error:

TypeError: <Status.success: 0> is not JSON serializable

How can I avoid that?

解决方案

If you want to encode an arbitrary enum.Enum member to JSON and then decode it as the same enum member (rather than simply the enum member's value attribute), you can do so by writing a custom JSONEncoder class, and a decoding function to pass as the object_hook argument to json.load() or json.loads():

PUBLIC_ENUMS = {
    'Status': Status,
    # ...
}

class EnumEncoder(json.JSONEncoder):
    def default(self, obj):
        if type(obj) in PUBLIC_ENUMS.values():
            return {"__enum__": str(obj)}
        return json.JSONEncoder.default(self, obj)

def as_enum(d):
    if "__enum__" in d:
        name, member = d["__enum__"].split(".")
        return getattr(PUBLIC_ENUMS[name], member)
    else:
        return d

The as_enum function relies on the JSON having been encoded using EnumEncoder, or something which behaves identically to it.

The restriction to members of PUBLIC_ENUMS is necessary to avoid a maliciously crafted text being used to, for example, trick calling code into saving private information (e.g. a secret key used by the application) to an unrelated database field, from where it could then be exposed (see https://chat.stackoverflow.com/transcript/message/35999686#35999686).

Example usage:

>>> data = {
...     "action": "frobnicate",
...     "status": Status.success
... }
>>> text = json.dumps(data, cls=EnumEncoder)
>>> text
'{"status": {"__enum__": "Status.success"}, "action": "frobnicate"}'
>>> json.loads(text, object_hook=as_enum)
{'status': <Status.success: 0>, 'action': 'frobnicate'}

这篇关于将枚举成员序列化为 JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆