Si desea codificar un enum.Enummiembro arbitrario en JSON y luego decodificarlo como el mismo miembro de enumeración (en lugar de simplemente el valueatributo del miembro de enumeración ), puede hacerlo escribiendo una JSONEncoderclase personalizada y una función de decodificación para pasar como object_hookargumento json.load()ao 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
La as_enumfunción se basa en que el JSON se haya codificado usando EnumEncoder, o algo que se comporte de manera idéntica.
La restricción a los miembros de PUBLIC_ENUMSes necesaria para evitar que se utilice un texto creado con fines malintencionados para, por ejemplo, engañar al código de llamada para que guarde información privada (por ejemplo, una clave secreta utilizada por la aplicación) en un campo de base de datos no relacionado, desde donde podría quedar expuesto. (ver http://chat.stackoverflow.com/transcript/message/35999686#35999686 ).
Uso de ejemplo:
>>> 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'}