Javascript JSON Date 反序列化
Javascript JSON Date Deserialization
我正在尝试反序列化一个包含javascript日期的json对象。在对象上调用 JSON.stringify 时,日期将序列化为未正确反序列化回日期的字符串。我尝试使用带有chrome,IE和FF的本机浏览器实现以及使用jquery来反序列化对象。两者都给出了一些结果。这是片段:
var obj = {Date: new Date()};
var objSer = JSON.stringify(obj);
var objDeser = JSON.parse(objSer);
var objJqDeser = $.parseJSON(objSer);
function getYear(value){
try{
return value.getYear();
}
catch(err){
return err;
}
}
$("#orig").text("Orig Year: " + getYear(obj.Date));
$("#deser").text("Deser Year: " + getYear(objDeser.Date));
$("#jqDeser").text("JqDeser Year: " + getYear(objJqDeser.Date));
我希望objDeser.Date是一个js日期而不是一个字符串。您可以在此处看到此问题的实际效果:http://jsbin.com/unijud/24/edit。是否有任何 js 库可以在构建 javascript 对象时正确反序列化日期?
JSON.parse
有一个鲜为人知的第二个参数:"齐磊"函数。这正是用于此目的:在初始解析期间将日期字符串恢复为Date
对象(或者,假设是要从字符串转换的任何其他类型的对象)。
有一篇关于这个的SO文章,这里有一篇博客文章,其中包括一个实现示例和一个函数,该函数将在解析为Date
之前对几个常见的日期编码(ISO和奇怪的.NET AJAX格式)进行属性检查。
这是该博客文章fwiw中的关键功能:
// JSON date deserializer
// use as the second, 'reviver' argument to JSON.parse();
if (window.JSON && !window.JSON.dateParser) {
var reISO = /^('d{4})-('d{2})-('d{2})T('d{2}):('d{2}):('d{2}(?:'.'d*))(?:Z|('+|-)(['d|:]*))?$/;
var reMsAjax = /^'/Date'((d|-|.*)')['/|'']$/;
JSON.dateParser = function (key, value) {
// first, just make sure the property is a string:
if (typeof value === 'string') {
// then, use regex to see if it's an ISO-formatted string
var a = reISO.exec(value);
if (a) {
// if so, Date() can parse it:
return new Date(value);
}
// otherwise, see if it's a wacky Microsoft-format string:
a = reMsAjax.exec(value);
if (a) {
// and perform some jujitsu to make use of it:
var b = a[1].split(/[-+,.]/);
return new Date(b[0] ? +b[0] : 0 - +b[1]);
}
// here, you could insert any additional tests and parse instructions you like, for other date syntaxes...
}
// important: you need to return any values you're not parsing, or they die...
return value;
};
}
// use: JSON.parse(json,JSON.dateParser);
(关于 ISO 8601 日期的正确正则表达式有很多意见。扬子晚报.此外,没有特别的理由将函数打到全局 JSON 对象上。您可以在任何您喜欢的地方存储/引用它。)
我采纳了@LastCoder建议,写了一个简单的实现。它似乎正在做我想做的事情。
var jsonDates = {
dtrx2: /'d{4}-'d{2}-'d{2}/,
parse: function(obj){
var parsedObj = JSON.parse(obj);
return this.parseDates(parsedObj);
},
parseDates: function(obj){
// iterate properties
for(pName in obj){
// make sure the property is 'truthy'
if (obj[pName]){
var value = obj[pName];
// determine if the property is an array
if (Array.isArray(value)){
for(var ii = 0; ii < value.length; ii++){
this.parseDates(value[ii]);
}
}
// determine if the property is an object
else if (typeof(value) == "object"){
this.parseDates(value);
}
// determine if the property is a string containing a date
else if (typeof(value) == "string" && this.dtrx2.test(value)){
// parse and replace
obj[pName] = new Date(obj[pName]);
}
}
}
return obj;
}
};
jsbin上有一个活的例子。有关要点的参考资料。
JavaScript 表示日期,我发现 JSON 使用 ISO 8601,这是一种特定的字符串格式将日期编码为字符串。不过,当我上次检查时,对于日期格式应该是什么样子,还没有官方标准。 主要的浏览器使用 ISO 8601 作为 JSON 日期编码格式。
因此,日期被编码为 ISO 8601 字符串,然后在序列化和反序列化 JSON 时像常规字符串一样使用。
话虽如此,ISO 日期可以通过使用 JavaScript Date 构造函数转换为 JavaScript 日期,该构造函数接受各种输入来构造日期,ISO 8601 就是其中之一。
获取今天的日期:
var curDate = new Date();
document.write(curDate); //Mon Feb 01 2016 12:57:12 GMT-0600 (Central Standard Time)
将其解析为字符串:
var dateStr = JSON.parse(JSON.stringify(curDate));
document.write(dateStr);//2016-02-01T18:59:35.375Z
然后使用构造函数将其转换回javascript日期:
var date = new Date(dateStr);
document.write(date); //Mon Feb 01 2016 12:59:35 GMT-0600 (Central Standard Time)
JSON 规范不包含日期的特殊格式。因此,它们通常序列化为字符串,有时带有特殊标记,以指示如果语言支持它们,则应将其视为 Date 对象。因此,大多数(所有?)浏览器原生 JSON 解析器无法正确往返 Date 对象。
有几个很好的库可以帮助解决这个问题 - 我非常喜欢MomentJS,尽管我过去也使用过datejs。您只需要遍历对象,并在解析后将正确的字段转换为 Date 对象。
我发现记住 JSON 格式比 JavaScript 对象文字表示法更具限制性很有帮助。
es5 能够像2018-04-03T22:00:00...
一样解析日期,就像Date
构造函数中的日期一样。(例如 new Date("2018-04-03T22:00:00...");
.
对于像我这样正在从 JSON Web 响应中搜索自动日期反序列化的人来说,这可能很方便。
/**
* Iterates over all entries of the input object and replace the string dates with the objects of {@link Date}.
*/
function fixDateObjects(responseBody) {
if (responseBody) {
const regex = /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}/;
for (const [key, value] of Object.entries(responseBody)) {
const val = String(value);
if (val.startsWith('[object Object]')) {
fixDateObjects(value);
}
if (val.match(regex)) {
responseBody[key] = new Date(val);
}
}
}
}
说明:它遍历 JSON(responseBody) 的所有对象条目,并将字符串日期(与给定的正则表达式匹配)替换为new Date(str)
对象。
结果:这为您提供了进一步处理的自由。现在,您已完全反序列化所有日期字符串。
//usage
function parseBody(response) {
fixDateObjects(response);
console.log(response.someDate); // Mon Aug 30 2021 22:45:59 GMT+0200 (...)
// further processing
}
您可以手动将所需的所有 Date 函数添加到 String.prototype 中。
String.prototype.getYear = function() {
return Date.parse(this).getYear();
};
var obj = {date: new Date()};
var dtObj = JSON.parse(JSON.stringify(obj));
console.log(dtObj.date.getYear());
或者,您可以覆盖 JSON.parse 并让它遍历结果对象,查找与时间戳正则表达式匹配的字符串,然后将它们转换为 Date 对象。
var JSON_parse = JSON.parse;
JSON.parse = function(str) {
var res = JSON_parse(str);
findAndConvertStringsToDates(res);
return res;
}
编辑 这是我为实现而拼凑的内容
(function() {
var jsonParse = JSON.parse;
var reDate = /^'d{4}-'d{2}-'d{2}T'd{2}:'d{2}:'d{2}'.'d{3}Z$/i;
function jsonDate(obj) {
var type = typeof(obj);
if(type == 'object') {
for(var p in obj)
if(obj.hasOwnProperty(p))
obj[p] = jsonDate(obj[p]);
return obj;
} else if(type == 'string' && reDate.test(obj)) {
return new Date(obj);
}
return obj;
}
JSON.parse = function(str) { return jsonDate(jsonParse(str)); }
})();
/*
* Tests
*/
var dt = JSON.parse(JSON.stringify({date: new Date()}));
console.log(typeof(dt.date));
console.log(JSON.parse(JSON.stringify(null)));
console.log(JSON.parse(JSON.stringify(123)));
console.log(JSON.parse(JSON.stringify("test")));
console.log(JSON.parse(JSON.stringify(new Date())));
console.log(JSON.parse(JSON.stringify([1,new Date(),2])));
console.log(JSON.parse(JSON.stringify({d: new Date(), d2: {d3: new Date(), d4: [0,new Date(),4]}})));
- 有没有一个Nodejs库可以序列化和反序列化命名组件的路径(比如URL路径名)
- 是否可以在javascript中反序列化java对象
- 如何在C#中反序列化json对象
- Nservicekit反序列化
- 无法反序列化 java.util.List 的实例VALUE_STRING
- 正在反序列化jQuery.Serialize的结果(到数组,而不是到窗体)
- 使用 JavaScript 进行反序列化
- Three.js-如何反序列化几何体.toJSON()?(几何体.fromJSON在哪里?)
- .NET服务中的JSON反序列化-can'不能解决这个问题
- 如何:从javascript反序列化C#对象
- 护照.js:如何避免序列化和反序列化用户
- 如何在 Express/Node.js 中反序列化 JSON 数据
- 在 javascript 中序列化和反序列化数组
- PHP 反序列化 JS 序列化的变量字符串
- Javascript:反序列化对象和混合方法
- 如何使用 Dojo.fromJson 反序列化包含控制字符的 Json 对象
- 当错误时清除cookie 使用护照反序列化用户.js
- 部分平展的 JSON 的反序列化
- Web API可以't反序列化Javascript Date.toISOString()
- Javascript JSON Date 反序列化