Wenn Sie ein beliebiges enum.EnumMitglied in JSON codieren und es dann als dasselbe Aufzählungselement (und nicht nur als valueAttribut des Aufzählungsmitglieds ) dekodieren möchten , können Sie dies tun, indem Sie eine benutzerdefinierte JSONEncoderKlasse und eine Dekodierungsfunktion schreiben , die als object_hookArgument an json.load()oder übergeben wird 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
Die as_enumFunktion basiert darauf, dass der JSON mit codiert EnumEncoderwurde oder etwas, das sich identisch mit ihm verhält.
Die Beschränkung auf Mitglieder von PUBLIC_ENUMSist erforderlich, um zu verhindern, dass ein böswillig gestalteter Text verwendet wird, um beispielsweise den Aufruf von Code zum Speichern privater Informationen (z. B. eines von der Anwendung verwendeten geheimen Schlüssels) in einem nicht verwandten Datenbankfeld zu betrügen, von wo aus sie dann verfügbar gemacht werden könnten (Siehe http://chat.stackoverflow.com/transcript/message/35999686#35999686 ).
Anwendungsbeispiel:
>>> 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'}