如何解析 JSON 以接收 JavaScript 中的 Date 对象?

IT技术 javascript json datetime
2021-02-01 14:46:20

我有以下一段 JSON:

\/Date(1293034567877)\/

这是此 .NET 代码的结果:

var obj = DateTime.Now;
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
serializer.Serialize(obj).Dump();

现在我面临的问题是如何在 JavaScript 中从 this 创建一个 Date 对象。我所能找到的只是令人难以置信的正则表达式解决方案(许多包含错误)。

很难相信没有优雅的解决方案,因为这一切都在 JavaScrip 中,我的意思是 JavaScript 代码试图读取 JSON(JavaScript Object Notation),它应该是一个 JavaScript 代码,目前事实证明这不是因为 JavaScript 不能做好这里。

我还看到了一些我无法使用的 eval 解决方案(除了被指出为安全威胁之外)。

真的没有办法以优雅的方式做到这一点吗?

没有真正答案的类似问题:
How to parse ASP.NET JSON Date format with GWT

6个回答

JSON.parse函数接受一个可选的 DateTime reviver 函数。您可以使用这样的函数:

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

然后打电话

JSON.parse(somejsonstring, dateTimeReviver);

你的日期会出来的。

我不得不像这样修改正则表达式 /\/Date((-?\d*))\// 以便它也能够处理负数。当您有一个由 .NET 转换为 JSON 的非常旧的 DateTime(在 Epoch 之前)时,会出现负数。
2021-03-17 14:46:20
我从来不知道这个功能 - 这太有用了!
2021-03-18 14:46:20
@ClearCloud8:你错过了反斜杠:/\/Date\((-?\d*)\)\//
2021-03-20 14:46:20
这种在原始类型(字符串)中编码非原始类型数据的做法是疯狂的。使用有意义的属性对 JSON 对象中的日期进行编码,或者更进一步,在 JSON 对象中包含一个“$type”属性,以便解析/反序列化例程可以适当地恢复类型,如果您想打包所有内容,甚至可以使用自定义转换器将信息转换为单个属性值,例如“ticks”或“ms_since_epoch”。
2021-03-26 14:46:20
为什么不a = Date.parse(value)代替/\/Date\((\d*)\)\//.exec(value);
2021-04-08 14:46:20

日期没有标准的 JSON 表示。您应该按照@jAndy 的建议进行操作,而根本不要序列化 ​​a DateTime只需发送一个 RFC 1123 日期字符串ToString("r")或一个来自 Unix-epoch 的秒数,或者您可以在 JavaScript 中使用的其他内容来构造一个Date.

JSON 支持数字、字符串、对象、数组以及字面量 true、false 和 null。由于 Date 不是这些,它是一个复杂的类型,应该存储为一个对象,而不是一个字符串,因此您可以在特殊成员中包含类型信息,例如类型名称,例如“$type”,它永远不会解析为真实对象成员。此类元成员可用于稍后将 JSON 对象恢复为强类型运行时对象。我认为在字符串中粘贴日期的做法是愚蠢的,因为它不必要地创建了保留字符串模式并试图在每个字符串上匹配它们。
2021-03-13 14:46:20
谢谢我走上了一条死路,你是第一个指出 JSON 不支持日期类型的人。
2021-03-30 14:46:20
现在有一个标准的 JSON 日期格式。 tools.ietf.org/html/rfc7493#section-4.3
2021-04-08 14:46:20

这个来自Roy Tinker 的回答在这里

var date = new Date(parseInt(jsonDate.substr(6)));

正如他所说:substr 函数取出“/Date(”部分,parseInt 函数获取整数并忽略末尾的“)/”。结果数字被传递到 Date 构造函数中。

另一种选择是简单地在 ASP 端正确格式化您的信息,以便 JavaScript 可以轻松读取它。考虑为您的日期执行此操作:

DateTime.Now()

应该返回这样的格式:

7/22/2008 12:11:04 PM

如果您将其传递给这样的 JavaScriptDate构造函数:

var date = new Date('7/22/2008 12:11:04 PM');

变量date现在持有这个值:

Tue Jul 22 2008 12:11:04 GMT-0700 (Pacific Daylight Time)

自然地,您可以将此DateTime对象格式化为 JSDate构造函数接受的任何类型的 string/int

一个确定的答案,直到“考虑为您的约会对象这样做…… ”。建议引入依赖于实现的解析和时区问题的非标准格式不是一个好主意。OP 格式更可取(虽然不理想)。
2021-03-15 14:46:20
给我任何线索的第一个答案
2021-03-19 14:46:20
永远不要依赖默认的日期<->字符串转换格式。使用 Epoch 以来的毫秒数,它停留在数字类型域中,更加简单和可靠。
2021-03-22 14:46:20
这个答案提出了两种解决方案——第一个是正确的(parseInt),第二个是错误的,所以不确定是投赞成票还是反对票!简单地作为字符串输出的问题是,如果服务器在一个国家(例如美国)而浏览器在另一个国家(例如英国),则日期很容易向后翻转。
2021-04-04 14:46:20
谢谢 treeface,这个答案最近帮我解决了一些问题!
2021-04-09 14:46:20

如果您在 JSON 中使用 JavaScript 样式 ISO-8601 日期,您可以使用它,来自MDN

const jsonDate = (new Date()).toJSON();
const backToDate = new Date(jsonDate);
console.log(jsonDate); //2015-10-26T07:46:36.611Z

创建ISO-8601 日期字符串

myDate.toISOString()
@aslop - 如果用户无法将日期与 ISO 相互转换,那么 JSON 是最少的问题。
2021-03-29 14:46:20
确实非常优雅,但这与问题中提到的特定日期格式无关。
2021-04-05 14:46:20
imo这是最优雅的答案,应该是公认的答案。
2021-04-11 14:46:20

您可以在 JavaScript 中将 JSON 日期转换为普通日期格式。

var date = new Date(parseInt(jsonDate.substr(6)));