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