Wenn Sie ein beliebiges enum.Enum
Mitglied in JSON codieren und es dann als dasselbe Aufzählungselement (und nicht nur als value
Attribut des Aufzählungsmitglieds ) dekodieren möchten , können Sie dies tun, indem Sie eine benutzerdefinierte JSONEncoder
Klasse und eine Dekodierungsfunktion schreiben , die als object_hook
Argument 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_enum
Funktion basiert darauf, dass der JSON mit codiert EnumEncoder
wurde oder etwas, das sich identisch mit ihm verhält.
Die Beschränkung auf Mitglieder von PUBLIC_ENUMS
ist 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'}