Se você deseja codificar um enum.Enummembro arbitrário para JSON e, em seguida, decodificá-lo como o mesmo membro enum (em vez de simplesmente o valueatributo do membro enum ), você pode fazer isso escrevendo uma JSONEncoderclasse personalizada e uma função de decodificação para passar como o object_hookargumento 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_enumfunçã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'}