【问题标题】:Why does JSON.stringify screw up my datetime object?为什么 JSON.stringify 搞砸了我的 datetime 对象?
【发布时间】:2012-02-29 22:48:25
【问题描述】:
{ id: 1533,
  story_type_id: 1,
  content_id: 470,
  created_at: Sun, 05 Feb 2012 07:02:43 GMT,
  updated_at: Sun, 05 Feb 2012 07:02:43 GMT,
  type_name: 'post' }

我有一个 JSON 对象,上面有“日期时间”字段。这是完美的。但是当我对它进行字符串化(我想将它存储在缓存中)时,我得到了这种格式:

"created_at":"2012-02-05T07:02:43.000Z"

这会导致问题,因为当我想 JSON.parse 这个时,突然它不再是 datetime 格式并且它与我的其他格式不兼容。

我可以做些什么来解决这个问题?我在整个应用程序中到处都是“created_at”。我不想手动更改每一个。

【问题讨论】:

  • 大概您正在序列化这些日期以将它们存储在 localStorage 中。在这种情况下,您可以通过使用像 rhaboo 这样的包装库来避免像这样和类似的仇恨。

标签: javascript string json node.js


【解决方案1】:

实际上可以修改 Date 对象如何序列化为 JSON。结合 reviver 功能,可以创建一个双向解决方案,该解决方案将自动进行序列化,并可轻松用于反序列化。

首先像这样修改序列化:

Date.prototype.toJSON = function() { return "{timestamp}+" . this.getTime() }

这会将 Date 对象的表示更改为带有前缀作为标记的 UNIX 时间戳:

> json = JSON.stringify({test:new Date()});
"{"test":"{timestamp}1380164268633"}"

然后你可以创建一个 reviver 函数,它会自动过滤掉这些值:

function json_deserialize_helper(key,value) {
  if ( typeof value === 'string' ) {
    var regexp;
    regexp = /^{timestamp}(\d*)$/.exec(value);
    if ( regexp ) {
      return new Date(+regexp[1]);
    }
  }
  return value;
}

(信用:这段代码基本上是从这个答案中复制的一个相关问题:https://stackoverflow.com/a/14509447/2572897

现在有了这个设置,我们之前的结果的反序列化将再次产生一个 Date 对象:

> JSON.parse(json, json_deserialize_helper);
Object {test: Thu Sep 26 2013 04:57:48 GMT+0200 (CEST)}

或者您可以选择不修改序列化,而是使用正则表达式捕获标准序列化格式:

function json_deserialize_helper(key,value) {
  if ( typeof value === 'string' ) {
    var regexp;
    regexp = /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ$/.exec(value);
    if ( regexp ) {
      return new Date(value);
    }
  }
  return value;
}

例子:

> json = JSON.stringify({test:new Date()})
"{"test":"2013-09-26T03:05:26.563Z"}"
> JSON.parse(json, json_deserialize_helper)
Object {test: Thu Sep 26 2013 05:05:26 GMT+0200 (CEST)}

【讨论】:

  • 这真的取决于字段名称。如果有很多字段必须在 Date 实例中怎么办?处理 reviever 函数中的所有字段?或者有没有可以检测日期格式的正则表达式?
  • 不依赖于字段名。再次检查代码。有一个正则表达式。您可能将此与另一个实际上取决于字段名称的答案混淆了。
【解决方案2】:

没有特殊的方法可以在 JSON 中序列化 Date 对象。这就是您获得标准化字符串表示的原因。您需要将它们转换回Date 对象,方法是将它们传递给Date 构造函数。

item['created_at'] = new Date(item['created_at']);

更新:使用 reviver 函数(请参阅 cmets),您可以取回 Date 对象。

var item = JSON.parse(row, function (key, value) {
  if (key === 'created_at') {
    return new Date(value);
  } else {
    return value;
  }
});

【讨论】:

  • 所以我无能为力了吗?
  • 不,我不这么认为。您必须以其他方式存储它。
  • Date 对象是 JavaScript 原生的,但 JSON 是一种用于在平台之间传输数据的序列化机制。如果它允许对原生对象和函数进行序列化,那么将 JSON 从 JS 传输到 PHP 的系统就会崩溃。您可能需要研究 JSON reviver 方法。
  • @JanKuča 如果我这样存储它会怎样,但在检索过程中,我会遍历每个键并检查它是否是日期。如果是这样,请将 new Date() 应用于它? stackoverflow.com/questions/9194576/…
  • @JanKuča,如果我不知道“created_at”部分怎么办?我有很多这样的...我不知道键名。我将不得不使用正则表达式来检查它是否是一个日期。
【解决方案3】:

Date.prototype.toJSON = function() { return moment(this).format('L'); }

您可以阅读更多关于时刻文档和定制您想要返回的日期类型的信息。

【讨论】:

    【解决方案4】:
    var date = new Date();
    console.log(date);//Mon Jun 11 2018 10:14:33 GMT+0430 (Iran Daylight Time)
    var json = JSON.stringify(date);
    console.log(json);//"2018-06-11T05:44:33.590Z"
    var dateStr = JSON.parse(json);  
    console.log(dateStr);//2018-06-11T05:44:33.590Z
    var date = new Date(dateStr);
    console.log(date);//Mon Jun 11 2018 10:14:33 GMT+0430 (Iran Daylight Time)
    

    https://weblog.west-wind.com/posts/2014/Jan/06/JavaScript-JSON-Date-Parsing-and-real-Dates

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-05
      • 2014-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      相关资源
      最近更新 更多