任意のenum.Enum
メンバーをJSONにエンコードしてから、(単に列挙型メンバーのvalue
属性ではなく)同じ列挙型メンバーとしてデコードする場合は、カスタムJSONEncoder
クラスと、またはにobject_hook
引数として渡すデコード関数を記述します。:json.load()
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
関数は、を使用してエンコードされたJSON EnumEncoder
、またはそれと同じように動作するものに依存しています。
のメンバーへの制限PUBLIC_ENUMS
は、悪意を持って作成されたテキストが使用されて、たとえば、呼び出しコードをだまして個人情報(アプリケーションで使用される秘密鍵など)を無関係のデータベースフィールドに保存させ、そこから公開されるのを防ぐために必要です。 (http://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'}