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


117

我有以下一段JSON:

\/Date(1293034567877)\/

.NET代码的结果:

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

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

很难相信没有完美的解决方案,因为这都是JavaScrip中的全部,我的意思是JavaScript代码试图读取应该是JavaScript代码的JSON(JavaScript对象表示法),目前看来,这并不是因为JavaScript无法在这里做好。

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

真的没有办法优雅地做到这一点吗?

没有真实答案的类似问题:
如何使用GWT解析ASP.NET JSON日期格式


2
您可以将时间戳传递给客户端,然后调用new Date()它。
jAndy 2010年

如果我有时间戳,可以,但是我有JSON,JavaScript显然不懂[sic!]
Piotr Owsiak 2010年

Answers:


51

没有日期的标准JSON表示形式。您应该执行@jAndy建议的操作,而不要完全序列化a DateTime;只需发送RFC 1123日期字符串ToString("r")或从Unix纪元开始的秒数,或可以在JavaScript中使用的其他内容即可构造一个Date


3
谢谢,我走了一条死路,您是第一个指出JSON不支持Date类型的人。
Piotr Owsiak 2010年

3
JSON支持数字,字符串,对象,数组以及文字true,false和null。由于Date都不是,所以它是一个复杂的类型,应该存储为一个对象,而不是一个字符串,因此您可以在诸如“ $ type”这样的特殊成员中包含类型信息,例如类型名称,而这些类型信息永远都不会解析为真实对象成员。此类元成员可用于稍后将JSON对象恢复为强类型的运行时对象。我认为在字符串中粘贴日期的做法很愚蠢,因为它不必要地创建了保留的字符串模式,并试图在每个字符串上匹配它们。
Triynko 2013年

4
现在有一个标准的JSON日期格式。 tools.ietf.org/html/rfc7493#section-4.3
Bryan Larsen

128

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);

您的约会将会正确。


1
很好发现,非常有用。
noup

5
以原始类型(字符串)编码非原始类型数据的这种做法是疯狂的。使用有意义的属性在JSON对象中编码日期,或者甚至更进一步,在JSON对象中包含“ $ type”属性,以便解析/反序列化例程可以适当地恢复类型,甚至如果要打包所有内容,都可以使用自定义转换器将该信息转换为单个属性值,例如“ ticks”或“ ms_since_epoch”。
Triynko

7
我必须像这样/// Date((-?\ d *))\ //修改正则表达式,以便它也能够处理负数。当您有一个很旧的DateTime(在Epoch之前)被.NET转换为JSON时,将出现负数。
2014年

@ ClearCloud8:您错过了反斜杠:/ \ / Date \((-?\ d *)\)\ //
Jerther

1
我从未听说过此功能-如此有用!
凯尔达

50

罗伊·廷克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

如果将其传递给这样的JavaScript Date构造函数:

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对象格式化为JS Date构造函数接受的任何类型的字符串/整数。


谢谢treeface,这个答案最近帮了我一些忙!
Malice

4
永远不要依赖默认的日期<->字符串转换格式。由于Epoch停留在数值类型域中,因此使用毫秒数要简单得多且可靠得多。
JohanBoulé2012年

2
这个答案提出了两种解决方案-第一种是正确的(parseInt),第二种是错误的,因此不确定是赞成还是赞成!如果服务器在一个国家(例如美国)中,而浏览器在另一个国家(例如英国)中,则仅以字符串形式输出的问题是日期很容易向后翻转。
mike nelson

给我任何线索的第一个答案
Nick.McDermaid '16

一个好的答案,直到“ 考虑为您的约会... ”。建议采用引入实现依赖的解析和时区问题的非标准格式不是一个好主意。OP格式是可取的(尽管不理想)。
RobG

21

如果您在JSON中使用JavaScript样式ISO8601日期,则可以从MDN使用此日期

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

2
imo这是最优雅的答案,应该被接受。
约翰·

1
确实非常优雅,但这与问题中提到的特定日期格式无关。
asiop

@aslop-如果用户无法将日期与ISO转换为日期,则JSON最少。
LeeGee '18年

7

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

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

6

有什么问题:

new Date(1293034567877);

这将为我返回“ 2010年12月22日星期三16:16:07 GMT + 0000(GMT标准时间)”。

还是您需要从json中获取数字?


3
您的解决方案出了什么问题?那么1293034567877不是我拥有的JSON,对吗?另外,我不需要从JSON中获取数字,我需要从JSON中获取日期。我期望JavaScript不仅仅是使用regex可以完成所有工作。我需要我的代码易于阅读,并且看起来不像卡通诅咒。
Piotr Owsiak

7
我责怪.NET以奇怪的格式产生日期对象的序列化\/Date(1293034567877)\/。如果它是理智的,那么它只会输出纪元时间,您可以使用它来初始化Date对象。
昆汀2010年

2
@treeface:如果JSON不是JavaScript,那么我认为应该将教程和书籍归咎于这种常见的误解。无论如何,我很乐意接受纠正。关于您建议Date可以表示为String的建议,我可以说所有内容都可以表示为String,对吗?但这并不能使我们的工作变得更轻松,反而使人痛苦而痛苦。我想我的问题源于以下事实:我将JSON作为一种序列化格式(广告比XML占用更少的带宽并更好地与JavaScript一起使用)。事实证明并非如此,至少不是一件轻松的事。
Piotr Owsiak 2011年

1
@treeface:我用Google搜索了您对JSON的声明,发现JSON是JavaScript,实际上是JavaScript的子集。请参阅RFC#4627“ JavaScript对象表示法(JSON)的应用程序/ json媒体类型”并查找以下语句:“ JSON的设计目标是使其成为最小,可移植,文本和JavaScript的子集。” 现在,当我考虑它时,您可以在JSON上调用eval()似乎很明显。
Piotr Owsiak 2011年

1
@David Dorward:我宁愿在库(.NET,Java,Ruby,Python或您所使用的任何语言/平台)的内部深处实现增加的复杂性,而不是让细节由程序员处理。还要注意,您不需要在JSON中支持布尔和整数数据类型,只需将它们放在字符串中,对吧?您能想象从JSON中获取任何东西是多么糟糕吗?
Piotr Owsiak 2011年

2

我知道这是一个非常老的话题,但是我希望将其发布以帮助那些像我一样碰到这个话题的人。

如果您不关心使用第三方脚本,则可以使用moment,js。 然后可以使用.format()将其格式化为所需的格式。


2

日期永远是一场噩梦。回答您的旧问题,也许这是最优雅的方法:

eval(("new " + "/Date(1455418800000)/").replace(/\//g,""))

使用eval,我们将字符串转换为javascript代码。然后我们删除“ /”,进入replace函数的是一个正则表达式。当我们以new开头时,我们的句子将执行以下命令:

new Date(1455418800000)

现在,我很久以前就开始使用的一件事是用记号表示的长值...为什么?好了,本地化,不要再思考如何在每个服务器或每个客户端中配置日期了。实际上,我也在数据库中使用它。

对于这个答案也许已经很晚了,但是可以帮助任何人在这里。


顺便说一句,我的英语水平比以往任何时候都更糟...但是我想我已经使自己明白了。
加布里埃尔·安德烈斯·布兰科里尼

您的回答效果很好,帮助我摆脱了困境。谢谢。
BoredBsee

1

AngularJS也无法解析.NET JSON日期/Date(xxxxxxxxxxxxx)/字符串。

我通过将日期格式化为ISO 8601字符串表示形式而不是Date直接转储对象来解决此问题...

这是ASP.NET MVC代码的示例。

return Json(new { 
  date : DateTime.Now.ToString("O") //ISO 8601 Angular understands this format
});

我试过了,RFC 1123但是不起作用。.Angular将此视为字符串而不是Date。

return Json(new { 
  date : DateTime.Now.ToString("R") //RFC 1123 Angular won't parse this
});

0

我还没有使用.Net这样的东西。如果能够打印以下内容,则它应该可以工作。

请注意,除非您通过其他方式解析该JSON 字符串,或者仅期望用户拥有内置JSON解析器的现代浏览器,否则您需要使用JS框架或JSON2将服务器输出的JSON字符串解析为真实的JSON目的。

// JSON received from server is in string format
var jsonString = '{"date":1251877601000}';

//use JSON2 or some JS library to parse the string
var jsonObject =  JSON.parse( jsonString );

//now you have your date!
alert( new Date(jsonObject.date) );

维基链接

诸如Firefox 3.5和Internet Explorer 8之类的现代浏览器包括用于解析JSON的特殊功能。由于本机浏览器支持比eval()更有效和安全,因此有望在下一个ECMAScript标准中包含本机JSON支持。[6]


链接到JSON2文件

现场例子


我明白了,但是我与JSON和Date类型有关的问题是我需要明确地执行“ new Date(”),这是a)额外的工作b)需要传达给消费者的其他知识。我真的很失望地发现它是如何处理的,我基本上认为这是JSON规范中的错误。
Piotr Owsiak

0

这个问题的答案是,使用nuget获取JSON.NET,然后在您的JsonResult方法内部使用它:

JsonConvert.SerializeObject(/* JSON OBJECT TO SEND TO VIEW */);

在您的视图内,只需在javascript以下位置执行此操作:

JSON.parse(/* Converted JSON object */)

如果是ajax调用:

var request = $.ajax({ url: "@Url.Action("SomeAjaxAction", "SomeController")", dataType: "json"});
request.done(function (data, result) { var safe = JSON.parse(data); var date = new Date(safe.date); });

一旦JSON.parse被调用,您可以把JSON日期为new Date实例,因为JsonConvert创建了一个合适的ISO时刻


0
function parseJsonDate(jsonDate) {

    var fullDate = new Date(parseInt(jsonDate.substr(6)));
    var twoDigitMonth = (fullDate.getMonth() + 1) + ""; if (twoDigitMonth.length == 1) twoDigitMonth = "0" + twoDigitMonth;

    var twoDigitDate = fullDate.getDate() + ""; if (twoDigitDate.length == 1) twoDigitDate = "0" + twoDigitDate;
    var currentDate = twoDigitMonth + "/" + twoDigitDate + "/" + fullDate.getFullYear();

    return currentDate;
};

0

正如Callum所说,对我而言,最好的方法是将Controller方法更改为字符串而不是JsonResult。”

public string GetValues()
{
  MyObject.DateFrom = DateTime.Now;
  return JsonConvert.SerializeObject(MyObject);
}

通过ajax方法,您可以执行以下操作

 $.ajax({
 url: "/MyController/GetValues",
 type: "post",
 success: function (data) {
 var validData = JSON.parse(data);
//if you are using datepicker and you want set a format
$("#DateFrom").val($.datepicker.formatDate("dd/mm/yy", new Date(validData.DateFrom)));                                      
// if you want the date as returned
$("#DateFrom").val(new Date(validData.DateFrom))
}
});

0

使用eval函数的工作原理是只需要删除前面和后面的正斜杠。

var date1 = "/Date(25200000)/"
eval("new " + date1.substring(1, date1.length - 1));

产生1970年1月1日星期四GMT-0700(美国山区标准时间)


0

我遇到了一个外部API以这种格式提供日期的问题,有时甚至使用UTC差异信息也是如此/Date(123232313131+1000)/。我可以Date使用以下代码将其变成js 对象

var val = '/Date(123232311-1000)/';
var pattern = /^\/Date\([0-9]+((\+|\-)[0-9]+)?\)\/$/;
var date = null;

// Check that the value matches /Date(123232311-1000)/ format
if (pattern.test(val)) {
  var number = val.replace('/Date(', '',).replace(')/', '');
  if (number.indexOf('+') >= 0) {
    var split = number.split('+');
    number = parseInt(split[0]) + parseInt(split[1]);
  } else if (number.indexOf('-') >= 0) {
    var split = number.split('-');
    number = parseInt(split[0]) - parseInt(split[1]);
  } else {
    number = parseInt(number);
    date = new Date(number);
  }
}

-1
//
// formats a .net date into a javascript compatible date
//
function FormatJsonDate(jsonDt) 
{              
    var MIN_DATE = -62135578800000; // const

    var date = new Date(parseInt(jsonDt.substr(6, jsonDt.length-8)));                                                       
    return date.toString() == new Date(MIN_DATE).toString() ? "" : (date.getMonth() + 1) + "\\" + date.getDate() + "\\" + date.getFullYear(); 
}

2
据我了解代码,您没有返回日期对象。
JohanBoulé2012年

-1
function parseJsonDate(jsonDate) {

    var fullDate = new Date(parseInt(jsonDate.substr(6)));
    var twoDigitMonth = (fullDate.getMonth() + 1) + ""; if (twoDigitMonth.length == 1) twoDigitMonth = "0" + twoDigitMonth;

    var twoDigitDate = fullDate.getDate() + ""; if (twoDigitDate.length == 1) twoDigitDate = "0" + twoDigitDate;
    var currentDate = twoDigitMonth + "/" + twoDigitDate + "/" + fullDate.getFullYear();

    return currentDate;
};

//使用此功能

var objDate=parseJsonDate("\/Date(1443812400000)\/");
alert(objDate);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.