Ich möchte ein datetime.datetime-Objekt in serialisierter Form von Python mit JSON senden und in JavaScript mit JSON de-serialisieren. Was ist der beste Weg, dies zu tun?
javascript
python
json
Peter Mortensen
quelle
quelle
Antworten:
Sie können json.dumps den Parameter 'default' hinzufügen, um dies zu handhaben:
Welches ist ISO 8601 Format.
Eine umfassendere Standardhandlerfunktion:
Update: Ausgabe von Typ und Wert hinzugefügt.
Update: Behandle auch das Datum
quelle
dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime) else json.JSONEncoder().default(obj)
Bei sprachübergreifenden Projekten habe ich herausgefunden, dass Zeichenfolgen mit RfC 3339- Daten der beste Weg sind. Ein RfC 3339-Datum sieht folgendermaßen aus:
Ich denke, der größte Teil des Formats ist offensichtlich. Das einzig ungewöhnliche ist vielleicht das "Z" am Ende. Es steht für GMT / UTC. Sie können auch einen Zeitzonenversatz wie +02: 00 für MESZ (Deutschland im Sommer) hinzufügen. Ich persönlich bevorzuge es, alles in UTC zu behalten, bis es angezeigt wird.
Zum Anzeigen, Vergleichen und Speichern können Sie es in allen Sprachen im Zeichenfolgenformat belassen. Wenn Sie das Datum für Berechnungen benötigen, können Sie es in den meisten Sprachen einfach wieder in ein natives Datumsobjekt konvertieren.
Generieren Sie den JSON also wie folgt:
Leider akzeptiert der Date-Konstruktor von Javascript keine RfC 3339-Zeichenfolgen, aber im Internet sind viele Parser verfügbar.
huTools.hujson versucht, die häufigsten Codierungsprobleme im Python-Code zu behandeln, einschließlich Datums- / Datums- / Uhrzeitobjekten, während Zeitzonen korrekt behandelt werden.
quelle
datetime
: datetime.isoformat () als auch vonsimplejson
, wodurchdatetime
Objekteisoformat
standardmäßig als Zeichenfolgen ausgegeben werden . Kein manuellesstrftime
Hacken erforderlich .datetime
Objekten in dieisoformat
Zeichenfolge. Für michsimplejson.dumps(datetime.now())
ergibtTypeError: datetime.datetime(...) is not JSON serializable
json.dumps(datetime.datetime.now().isoformat())
Hier geschieht die Magie.Ich habe es herausgefunden.
Angenommen, Sie haben ein Python-Datum / Uhrzeit-Objekt, d , das mit datetime.now () erstellt wurde. Sein Wert ist:
Sie können es als ISO 8601-Datums- / Uhrzeitzeichenfolge in JSON serialisieren:
Das Beispiel-Datum / Uhrzeit-Objekt würde wie folgt serialisiert:
Dieser Wert kann nach dem Empfang in der Javascript-Ebene ein Datumsobjekt erstellen:
Ab Javascript 1.8.5 verfügen Date-Objekte über eine toJSON-Methode, die eine Zeichenfolge in einem Standardformat zurückgibt. Um das obige Javascript-Objekt wieder in JSON zu serialisieren, lautet der Befehl daher:
Welches würde Ihnen geben:
Diese in Python empfangene Zeichenfolge kann wieder in ein Datum / Uhrzeit-Objekt deserialisiert werden:
Dies führt zu dem folgenden Datum / Uhrzeit-Objekt, mit dem Sie begonnen haben und das daher korrekt ist:
quelle
Mit
json
können Sie JSONEncoder in Unterklassen unterteilen und die default () -Methode überschreiben, um Ihre eigenen benutzerdefinierten Serialisierer bereitzustellen:Dann können Sie es so nennen:
quelle
obj.isoformat()
. Sie können auch den allgemeinerendumps()
Aufruf verwenden, der andere nützliche Argumente (wieindent
) benötigt: simplejson.dumps (myobj, cls = JSONEncoder, ...)Hier ist eine ziemlich vollständige Lösung zum rekursiven Codieren und Decodieren von datetime.datetime- und datetime.date-Objekten unter Verwendung des Standardbibliotheksmoduls
json
. Dies erfordert Python> = 2.6, da der%f
Formatcode in der Formatzeichenfolge datetime.datetime.strptime () nur seitdem unterstützt wird. Wenn Sie Python 2.5 unterstützen möchten, löschen Sie die%f
und entfernen Sie die Mikrosekunden von der ISO-Datumszeichenfolge, bevor Sie versuchen, sie zu konvertieren. Natürlich verlieren Sie jedoch die Genauigkeit von Mikrosekunden. Für die Interoperabilität mit ISO-Datumszeichenfolgen aus anderen Quellen, die einen Zeitzonennamen oder einen UTC-Versatz enthalten können, müssen Sie möglicherweise vor der Konvertierung auch einige Teile der Datumszeichenfolge entfernen. Einen vollständigen Parser für ISO-Datumszeichenfolgen (und viele andere Datumsformate) finden Sie im Dateutil- Modul eines Drittanbieters .Die Dekodierung funktioniert nur, wenn die ISO-Datumszeichenfolgen Werte in einer JavaScript-Literalobjektnotation oder in verschachtelten Strukturen innerhalb eines Objekts sind. ISO-Datumszeichenfolgen, die Elemente eines Arrays der obersten Ebene sind, werden nicht dekodiert.
Dh das funktioniert:
Und das auch:
Dies funktioniert jedoch nicht wie erwartet:
Hier ist der Code:
quelle
datetime.datetime.utcnow().isoformat()[:-3]+"Z"
es ist, entspricht es genau dem, was JSON.stringify () in Javascript erzeugtWenn Sie sicher sind, dass nur Javascript den JSON verbraucht, übergebe ich Javascript-
Date
Objekte lieber direkt.Die
ctime()
Methode fürdatetime
Objekte gibt eine Zeichenfolge zurück, die das Javascript Date-Objekt verstehen kann.Javascript verwendet dies gerne als Objektliteral, und Sie haben Ihr Date-Objekt direkt eingebaut.
quelle
.ctime()
ist ein sehr schlechter Weg, um Zeitinformationen weiterzugeben,.isoformat()
ist viel besser. Was.ctime()
wegwirft, ist Zeitzone und Sommerzeit wegzuwerfen, als ob sie nicht existieren. Diese Funktion sollte beendet werden.Spät im Spiel ... :)
Eine sehr einfache Lösung besteht darin, die Standardeinstellung des JSON-Moduls zu patchen. Zum Beispiel:
Jetzt können Sie json.dumps () so verwenden, als hätte es datetime immer unterstützt ...
Dies ist sinnvoll, wenn Sie diese Erweiterung des JSON-Moduls benötigen, um immer aktiv zu werden, und die Art und Weise, wie Sie oder andere die JSON-Serialisierung verwenden (entweder im vorhandenen Code oder nicht), nicht ändern möchten.
Beachten Sie, dass einige das Patchen von Bibliotheken auf diese Weise als schlechte Praxis betrachten. Besondere Vorsicht ist geboten, wenn Sie Ihre Anwendung auf mehrere Arten erweitern möchten. In diesem Fall empfehle ich, die Lösung von Ramen oder JT zu verwenden und jeweils die richtige JSON-Erweiterung auszuwählen.
quelle
None
. Möglicherweise möchten Sie stattdessen eine Ausnahme auslösen.Der Community-Wiki-Antwort gibt es nicht viel hinzuzufügen, außer dem Zeitstempel !
Javascript verwendet das folgende Format:
Python-Seite (für den
json.dumps
Handler siehe die anderen Antworten):Wenn Sie dieses Z weglassen, können Frontend-Frameworks wie Angular das Datum nicht in der browser-lokalen Zeitzone anzeigen:
quelle
Auf der Python-Seite:
Auf der Javascript-Seite:
Dabei stammen die Daten aus Python
quelle
Mein Rat ist, eine Bibliothek zu benutzen. Es gibt mehrere auf pypi.org.
Ich benutze dieses, es funktioniert gut: https://pypi.python.org/pypi/asjson
quelle
Anscheinend ist das "richtige" JSON-Datumsformat (auch JavaScript) 2012-04-23T18: 25: 43.511Z - UTC und "Z". Ohne dieses JavaScript wird beim Erstellen eines Date () -Objekts aus der Zeichenfolge die lokale Zeitzone des Webbrowsers verwendet.
Für eine "naive" Zeit (was Python eine Zeit ohne Zeitzone nennt und dies als lokal voraussetzt) erzwingt das Folgende eine lokale Zeitzone, damit sie dann korrekt in UTC konvertiert werden kann:
Warum ist das so schwer?
quelle
Für die Datumskonvertierung von Python in JavaScript muss das Datumsobjekt ein bestimmtes ISO-Format haben, dh ein ISO-Format oder eine UNIX-Nummer. Wenn dem ISO-Format einige Informationen fehlen, können Sie zuerst mit Date.parse in die Unix-Nummer konvertieren. Darüber hinaus funktioniert Date.parse auch mit React, während ein neues Datum möglicherweise eine Ausnahme auslöst.
Wenn Sie ein DateTime-Objekt ohne Millisekunden haben, muss Folgendes berücksichtigt werden. ::
Das Beispieldatum kann nach einem API-Aufruf auch eine Variable im Objekt result.data sein.
Optionen zum Anzeigen des Datums im gewünschten Format (z. B. zum Anzeigen langer Wochentage) finden Sie im MDN-Dokument .
quelle