将 Enum 成员序列化为 JSON

新手上路,请多包涵

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

例如,这段代码:

 from enum import Enum
import json

class Status(Enum):
    success = 0

json.dumps(Status.success)

导致错误:

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

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

原文由 Bilal Syed Hussain 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.6k
2 个回答

如果您想将任意 enum.Enum 成员编码为 JSON,然后将其解码为相同的枚举成员(而不仅仅是枚举成员的 value 属性),您可以通过编写一个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

as_enum 函数依赖于使用 EnumEncoder 或与其行为相同的东西编码的 JSON。

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

用法示例:

 >>> 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'}

原文由 Zero Piraeus 发布,翻译遵循 CC BY-SA 4.0 许可协议

我知道这很旧,但我觉得这会对人们有所帮助。我刚刚解决了这个确切的问题,发现如果您使用的是字符串枚举,则将您的枚举声明为 str 的子类——适用于几乎所有情况:

 import json
from enum import Enum

class LogLevel(str, Enum):
    DEBUG = 'DEBUG'
    INFO = 'INFO'

print(LogLevel.DEBUG)
print(json.dumps(LogLevel.DEBUG))
print(json.loads('"DEBUG"'))
print(LogLevel('DEBUG'))

将输出:

 LogLevel.DEBUG
"DEBUG"
DEBUG
LogLevel.DEBUG

如您所见,加载 JSON 输出字符串 DEBUG 但它很容易转换回 LogLevel 对象。如果您不想创建自定义 JSONEncoder,这是一个不错的选择。

原文由 Justin Carter 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏