Ein Hinweis zum Codieren eines Objekts einer von Ihnen in Python definierten Klasse und zum Decodieren aus dem Json-Format. Referenzierte Seite:
Nehmen Sie diese Klasse als Beispiel.
import json
from datetime import date
class MyA:
def __init__(self, i=0, d=date.today()):
self.i = i #int type
self.d = d #Datumstyp
Zunächst müssen wir uns das Format des Objekts als Json-Daten vorstellen. Es scheint natürlich, dass das MyA-Objekt ein Objekt mit "i" und "würde" als Schlüssel ist. Auch die Datumsangaben können eine Zeichenfolge sein, aber lassen Sie uns sie mit der Toordinal-Methode schnell in eine Ganzzahl konvertieren. Dann zum Beispiel
a = MyA(i=100, d=date(year=2345, month=6, day=12))
Das a definiert als wird in die Json-Daten "{" i ": 100," d ": 856291}" konvertiert. Dies mag in Ordnung sein, kann aber langwierig sein, da Sie nicht wissen, auf welchen Typ Sie beim Dekodieren zurückgreifen sollen. Daher wird der Klassenname im Schlüssel "_type" gespeichert, und der Wert wird im Schlüssel "value" gespeichert. Infolgedessen sehen die Json-Daten folgendermaßen aus:
{ "_type": "MyA",
"value": {"i": 100,
"d": { "_type": "date",
"value": 856291}}}
Die Befehle dump und dumps in Pythons json-Bibliothek verwenden ein Argument namens cls. Hier können Sie Ihren eigenen Encoder angeben. Da JSONEncoder eine häufig verwendete Klasse ist, erstellen Sie darauf basierend Ihren eigenen Encoder. Was Sie wirklich tun müssen, ist eine Methode namens Standard neu zu definieren.
class MyEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, date):
return {'_type': 'date', 'value': o.toordinal()}
if isinstance(o, MyA):
return {'_type': 'MyA', 'value': o.__dict__}
return json.JSONEncoder.default(self, o)
Wie Sie sehen, müssen Sie nur schreiben, was jede Klasse direkt betrachtet, und die Bibliothek tut das Gute für die Rekursion. (Im Fall eines MyA-Klassenobjekts wird ein Wörterbuch zurückgegeben, und dort können Datumsangaben festgelegt werden.)
Es kann wie folgt ausgeführt werden.
a = MyA(100, date(year=2345, month=6, day=12))
js = json.dumps(a, cls=MyEncoder)
print(js)
Ausführungsergebnis:
{"_type": "MyA", "value": {"i": 100, "d": {"_type": "date", "value": 856291}}}
Dadurch wird auch ein Decoder erstellt, der auf einer Klasse namens JSONDecoder basiert. Wenn das Objekt der übergeordneten Klasse JSONDecoder erstellt wird, schreiben Sie es dieses Mal so, dass die erforderliche Dekodierung in der an die Variable object_hook übergebenen Funktion ausgeführt wird. Es sieht aus wie das:
class MyDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
json.JSONDecoder.__init__(self, object_hook=self.object_hook,
*args, **kwargs)
def object_hook(self, o):
if '_type' not in o:
return o
type = o['_type']
if type == 'date':
return date.fromordinal(o['value'])
elif type == 'MyA':
return MyA(**o['value'])
Ab o von object_hook wird das Ergebnis der normalen Decodierung übergeben. Im obigen Beispiel wird ein Wörterbuch mit "_type" und "value" als Schlüssel geliefert, sodass Sie den Code schreiben können, um ihn als Objekt der entsprechenden Klasse neu zu erstellen. Auch hier müssen Sie nicht über rekursive Verarbeitung nachdenken.
Nach der Ausführung zum Zeitpunkt der Codierung:
b = json.loads(js, cls=MyDecoder)
print(b.i, b.d)
Ausführungsergebnis:
100 2345-06-12
Recommended Posts