Якщо ви хочете закодувати довільний 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'}