将枚举成员序列化为 JSON [英] Serialising an Enum member to 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屋!