Se você deseja codificar um enum.Enum
membro arbitrário para JSON e, em seguida, decodificá-lo como o mesmo membro enum (em vez de simplesmente o value
atributo do membro enum ), você pode fazer isso escrevendo uma JSONEncoder
classe personalizada e uma função de decodificação para passar como o object_hook
argumento parajson.load()
ou 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
A as_enum
função depende do JSON ter sido codificado usando EnumEncoder
, ou algo que se comporta de forma idêntica a ele.
A restrição a membros de PUBLIC_ENUMS
é necessária para evitar que um texto elaborado com códigos maliciosos seja usado para, por exemplo, enganar o código de chamada para salvar informações privadas (por exemplo, uma chave secreta usada pelo aplicativo) em um campo de banco de dados não relacionado, de onde poderia ser exposto (consulte http://chat.stackoverflow.com/transcript/message/35999686#35999686 ).
Exemplo de uso:
>>> 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'}