Десериализация клиентских дат AJAX JSON
Вопрос
Учитывая следующее представление даты в формате JSON:
"\/Date(1221644506800-0700)\/"
Как вы десериализуете это в форму типа даты JavaScript?
Я пробовал использовать MS AJAX JavaScrioptSerializer, как показано ниже:
Sys.Serialization.JavaScriptSerializer.deserialize("\/Date(1221644506800-0700)\/")
Однако все, что я получаю обратно, - это буквальная строка date.
Решение
При условии, что вы знаете, что строка определенно является датой, я предпочитаю делать это :
new Date(parseInt(value.replace("/Date(", "").replace(")/",""), 10))
Другие советы
Бертран Леруа, который работал над ASP.NET Atlas/AJAX, описан дизайн вывода даты и времени JavaScriptSerializer и раскрыл происхождение таинственных ведущих и замыкающих косых черт.Он дал такую рекомендацию:
запустите простой поиск "\/ Дата((\ d +)) \/" и замените на "новая дата ($ 1)" перед оценкой (но после проверки)
Я реализовал это как:
var serializedDateTime = "\/Date(1271389496563)\/";
document.writeln("Serialized: " + serializedDateTime + "<br />");
var toDateRe = new RegExp("^/Date\\((\\d+)\\)/$");
function toDate(s) {
if (!s) {
return null;
}
var constructor = s.replace(toDateRe, "new Date($1)");
if (constructor == s) {
throw 'Invalid serialized DateTime value: "' + s + '"';
}
return eval(constructor);
}
document.writeln("Deserialized: " + toDate(serializedDateTime) + "<br />");
Это очень близко ко многим другим ответам:
- Используйте привязанное регулярное выражение, как это делал Серд Вишер - не забудьте ^ и $.
- Избегайте string.replace и опций 'g' или 'i' в вашем регулярном выражении."/Date(1271389496563) //Дата(1271389496563)/" вообще не должно работать.
Значение JSON - это строка, число, объект, массив, значение true, false или null.Так что это всего лишь строка.Официального способа представления дат в JSON не существует.Этот синтаксис взят из реализации asp.net ajax.Другие используют формат ISO 8601.
Вы можете разобрать это следующим образом:
var s = "\/Date(1221644506800-0700)\/";
var m = s.match(/^\/Date\((\d+)([-+]\d\d)(\d\d)\)\/$/);
var date = null;
if (m)
date = new Date(1*m[1] + 3600000*m[2] + 60000*m[3]);
Регулярное выражение, используемое в методе ASP.net AJAX deserialize, ищет строку, которая выглядит как "/Date(1234)/" (сама строка на самом деле должна содержать кавычки и косую черту).Чтобы получить такую строку, вам нужно будет экранировать кавычки и символы обратной косой черты, поэтому код javascript для создания строки выглядит как "\"\/Date(1234)\/\"".
Это сработает.
Sys.Serialization.JavaScriptSerializer.deserialize("\"\\/Date(1221644506800)\\/\"")
Это немного странно, но я обнаружил, что мне пришлось сериализовать дату, затем сериализовать возвращаемую из нее строку, а затем один раз десериализовать на стороне клиента.
Что-то вроде этого.
Script.Serialization.JavaScriptSerializer jss = new Script.Serialization.JavaScriptSerializer();
string script = string.Format("alert(Sys.Serialization.JavaScriptSerializer.deserialize({0}));", jss.Serialize(jss.Serialize(DateTime.Now)));
Page.ClientScript.RegisterStartupScript(this.GetType(), "ClientScript", script, true);
Для тех, кто не хочет использовать Microsoft Ajax, просто добавьте функцию-прототип в класс string.
Например.
String.prototype.dateFromJSON = function () {
return eval(this.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));
};
Не хотите использовать eval?Попробуйте что-нибудь простое, например
var date = new Date(parseInt(jsonDate.substr(6)));
В качестве дополнительного примечания, раньше я думал, что Microsoft вводит в заблуждение, используя этот формат.Однако спецификация JSON не очень ясна, когда дело доходит до определения способа описания дат в JSON.
На самом деле, momentjs поддерживает такой формат, вы могли бы сделать что-то вроде:
var momentValue = moment(value);
momentValue.toDate();
Это возвращает значение в формате даты javascript
Большое число - это стандартное время JS
new Date(1221644506800)
Ср. 17 сентября 2008 г. 19:41:46 GMT+1000 (EST)