2024-04-26 12:12:46 发布
网友
如何将PythonEnum成员序列化为JSON,以便将生成的JSON反序列化为Python对象?
Enum
例如,此代码:
from enum import Enum import json class Status(Enum): success = 0 json.dumps(Status.success)
导致错误:
TypeError: <Status.success: 0> is not JSON serializable
我怎样才能避免呢?
如果要将任意enum.Enum成员编码为JSON,然后解码 它作为同一个枚举成员(而不仅仅是枚举成员的value属性),您可以通过编写一个自定义的^{}类和一个解码函数作为object_hook参数传递给^{}或^{}:
enum.Enum
value
object_hook
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。
as_enum
EnumEncoder
对PUBLIC_ENUMS成员的限制是必要的,以避免使用恶意编制的文本,例如,欺骗调用代码将私有信息(例如,应用程序使用的密钥)保存到不相关的数据库字段中,然后从该字段将其公开(请参见http://chat.stackoverflow.com/transcript/message/35999686#35999686)。
PUBLIC_ENUMS
示例用法:
>>> 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'}
我知道这是旧的,但我觉得这会帮助人们。我刚刚解决了这个问题,发现如果您使用的是字符串枚举,那么将枚举声明为str的子类对于几乎所有情况都很有效:
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,这是一个不错的选择。
DEBUG
正确的答案取决于您打算如何处理序列化版本。
如果要取消对Python的序列化,请参见Zero's answer。
如果您的序列化版本将要使用另一种语言,则可能需要使用IntEnum,它将自动序列化为相应的整数:
IntEnum
from enum import IntEnum import json class Status(IntEnum): success = 0 failure = 1 json.dumps(Status.success)
这将返回:
'0'
如果要将任意} 类和一个解码函数作为} 或^{} :
enum.Enum
成员编码为JSON,然后解码 它作为同一个枚举成员(而不仅仅是枚举成员的value
属性),您可以通过编写一个自定义的^{object_hook
参数传递给^{as_enum
函数依赖于使用EnumEncoder
或与之行为相同的东西编码的JSON。对
PUBLIC_ENUMS
成员的限制是必要的,以避免使用恶意编制的文本,例如,欺骗调用代码将私有信息(例如,应用程序使用的密钥)保存到不相关的数据库字段中,然后从该字段将其公开(请参见http://chat.stackoverflow.com/transcript/message/35999686#35999686)。示例用法:
我知道这是旧的,但我觉得这会帮助人们。我刚刚解决了这个问题,发现如果您使用的是字符串枚举,那么将枚举声明为
str
的子类对于几乎所有情况都很有效:将输出:
如您所见,加载JSON会输出字符串
DEBUG
,但很容易将其返回到LogLevel对象中。如果不想创建自定义JSONEncoder,这是一个不错的选择。正确的答案取决于您打算如何处理序列化版本。
如果要取消对Python的序列化,请参见Zero's answer。
如果您的序列化版本将要使用另一种语言,则可能需要使用
IntEnum
,它将自动序列化为相应的整数:这将返回:
相关问题 更多 >
编程相关推荐