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'}
if isinstance(obj, Enum):
?Ich weiß, dass dies alt ist, aber ich denke, dass dies den Menschen helfen wird. Ich habe gerade genau dieses Problem durchgearbeitet und festgestellt, ob Sie Zeichenfolgenaufzählungen verwenden, und Ihre Aufzählungen als Unterklasse von
str
Arbeiten deklariert, die für fast alle Situationen gut geeignet sind :Wird ausgegeben:
Wie Sie sehen können, gibt das Laden des JSON die Zeichenfolge aus
DEBUG
, kann jedoch problemlos wieder in ein LogLevel-Objekt umgewandelt werden. Eine gute Option, wenn Sie keinen benutzerdefinierten JSONEncoder erstellen möchten.quelle
class LogLevel(str, Enum): DEBUG = 'Дебаг' INFO = 'Инфо'
in diesem Fallenum with str
keine Arbeit richtig (Die richtige Antwort hängt davon ab, was Sie mit der serialisierten Version tun möchten.
Wenn Sie wieder in Python unserialisieren möchten, lesen Sie die Antwort von Zero .
Wenn Ihre serialisierte Version in eine andere Sprache wechselt, möchten Sie wahrscheinlich
IntEnum
stattdessen eine verwenden, die automatisch als entsprechende Ganzzahl serialisiert wird:und das kehrt zurück:
quelle
Python3.4
und diese Antwort ist 3.4+ spezifisch.EnumMeta
anstelle vonIntEnum
Enum
, möglicherweise mit einemstr
Mixin -class MyStrEnum(str, Enum): ...
EnumMeta
, was nur als Metaklasse gedacht war. Beachten Sie stattdessen, dass die Implementierung vonIntEnum
ein Einzeiler ist und Sie dasselbe fürstr
mit erreichen könnenclass StrEnum(str, Enum): ...
.In Python 3.7 kann nur verwendet werden
json.dumps(enum_obj, default=str)
quelle
Ich mochte die Antwort von Zero Piraeus, änderte sie jedoch geringfügig, um mit der API für Amazon Web Services (AWS), bekannt als Boto, zu arbeiten.
Ich habe dann diese Methode zu meinem Datenmodell hinzugefügt:
Ich hoffe das hilft jemandem.
quelle
Wenn Sie
jsonpickle
den einfachsten Weg verwenden, sollten Sie wie folgt aussehen.Nach der Json-Serialisierung haben Sie wie erwartet
{"status": 0}
stattquelle
Das hat bei mir funktioniert:
Musste nichts anderes ändern. Offensichtlich erhalten Sie den Wert nur daraus und müssen andere Arbeiten ausführen, wenn Sie den serialisierten Wert später wieder in die Aufzählung konvertieren möchten.
quelle
JSONEncoder
irgendwo eine benutzerdefinierte Bibliothek ?