Unser Client wollte die Datums- und Uhrzeitwerte im Browser genauso anzeigen, wie sie in der Datenbank sind, und wir speichern sie als UTC in der Datenbank.JavaScriptSerializer UTC DateTime-Ausgaben
Zuerst hatten wir einige Probleme mit der Serialisierung und Javascript Seite. Die DateTime-Werte wurden zweimal verschoben - zunächst so, dass sie mit der lokalen Zeitzone der Maschine übereinstimmen und dann mit der Zeitzone im Browser übereinstimmen. Wir haben es behoben, indem wir dem JavaScriptSerializer einen benutzerdefinierten Konverter hinzugefügt haben. Wir haben die DateTime als DateTimeKind.Utc in der Serialize-Überschreibung markiert. Es war ein bisschen schwierig, die Daten aus dem Serialize zurückzugeben, aber wir fanden einen Uri-Hack, der dazu half, DateTime-Werte im selben JavaScriptSerializer/Date-Format (286769410010) zurückzugeben, aber ohne auf die Ortszeit zu wechseln. Auf der Javascript-Seite haben wir die KendoUI JS-Bibliothek gepatcht, um die konstruierten Date() -Objekte so zu versetzen, als ob sie UTC wären.
Dann begannen wir auf der anderen Seite zu arbeiten, Deserialisierung. Auch hier mussten wir unseren Code so anpassen, dass anstelle von JSON.stringify ein benutzerdefinierter Stringify verwendet wurde, der die Daten beim Konvertieren von der Ortszeit in UTC erneut ausgleicht. Alles schien bisher gut zu sein.
Aber schauen Sie auf diesen Test:
public void DeserialiseDatesTest()
{
var dateExpected = new DateTime(1979, 2, 2,
2, 10, 10, 10, DateTimeKind.Utc);
// this how the Dates look like after serializing
// anothe issue, unrelated to the core problem, is that the "\" might get stripped out when dates come back from the browser
// so I have to add missing "\" or else Deserialize will break
string s = "\"\\/Date(286769410010)\\/\"";
// this get deserialized to UTC date by default
JavaScriptSerializer js = new JavaScriptSerializer();
var dateActual = js.Deserialize<DateTime>(s);
Assert.AreEqual(dateExpected, dateActual);
Assert.AreEqual(DateTimeKind.Utc, dateActual.Kind);
// but some Javascript components (like KendoUI) sometimes use JSON.stringify
// for Javascript Date() object, thus producing the following:
s = "\"1979-02-02T02:10:10Z\"";
dateActual = js.Deserialize<DateTime>(s);
// If your local computer time is not UTC, this will FAIL!
Assert.AreEqual(dateExpected, dateActual);
// and the following fails always
Assert.AreEqual(DateTimeKind.Utc, dateActual.Kind);
}
Warum JavaScriptSerializer \/Date(286769410010)\/
Strings in UTC-Zeit deserialisieren aber 1979-02-02T02:10:10Z
in der lokalen Zeit?
Wir haben versucht, eine Deserialize Methode unserer Gewohnheit hinzuzufügen JavascriptConverter
aber das Problem ist, dass die Deserialize nie, wenn unsere Javascript die folgenden Typen hat aufgerufen:
public override IEnumerable<Type> SupportedTypes
{
get { return new List<Type>() { typeof(DateTime), typeof(DateTime?) }; }
}
ich denke, würde Deserialize nur, wenn SupportedTypes
genannt werden enthält Typen einiger komplexer Entitäten, die DateTime-Felder enthalten.
So JavaScriptSerializer
und JavascriptConverter
haben zwei Widersprüche:
- Serialize berücksichtigt einfache Typen in SupportedTypes für jeden Datenpunkt, aber Deserialize ignoriert es für einfache Typen
- Deserialize deserialisiert einige Daten als UTC und einige - als Ortszeit.
Gibt es eine einfache Möglichkeit, diese Probleme zu beheben? Wir haben ein wenig Angst, JavaScriptSerializer
mit einem anderen Serializer zu ersetzen, weil einige der Bibliotheken von Drittanbietern, die wir verwenden, auf bestimmte "features/bugs" von JavaScriptSerializer
angewiesen sind.
Ok - also ist das alles gut und gut und nützlich, aber was ist die Schwachsinn Entschuldigung für Msft nicht nur die Lieferung der besseren JSON-Bibliothek und die Buggy JavaScriptSerializer allein lassen? – nothingisnecessary