ASP.NET MVC JsonResultdate格式

我有一个控制器行动,有效地简单地返回我的模型的JsonResult。 所以,在我的方法中,我有如下的东西:

return new JsonResult(myModel); 

除了一个问题,这个效果很好。 在模型中有一个date属性,这似乎是在Json结果中返回,如下所示:

 "\/Date(1239018869048)\/" 

我应该如何处理date,以便按照我需要的格式返回? 或者我如何处理脚本中的上述格式?

只是为了扩大casperOne的答案 。

JSON规范不考虑date值。 MS不得不打个电话,他们select的path是利用javascript表示string中的一个小窍门:string文字“/”和“\ /”是一样的,string文字永远不会被序列化为“ \ /“(偶数”\ /“必须映射到”\\ /“)。

请参阅http://msdn.microsoft.com/en-us/library/bb299886.aspx#intro_to_json_topic2以获得更好的解释(向下滚动到“从JavaScript Literals到JSON”)

JSON的一个难点是没有date/时间文字。 许多人在第一次遇到JSON时都感到惊讶和失望。 没有date/时间文字的简单解释(安慰或不安慰)是JavaScript从未有过:JavaScript中对date和时间值的支持完全是通过Date对象提供的。 因此,大多数使用JSON作为数据格式的应用程序通常倾向于使用string或数字来表示date和时间值。 如果使用string,通常可以期望它是ISO 8601格式。 如果使用了一个数字,那么这个数值通常被认为是统一世界标准时间(UTC)的世纪时间以来的毫秒数,其中时代被定义为1970年1月1日午夜(UTC)。 同样,这仅仅是一个约定而不是JSON标准的一部分。 如果您正在与另一个应用程序交换数据,则需要检查其文档以查看它是如何在JSON文本中对date和时间值进行编码的。 例如,微软的ASP.NET AJAX既不使用所描述的约定。 相反,它将.NET DateTime值编码为JSONstring,其中string的内容是/ Date(ticks)/,其中tick表示自epoch(UTC)以来的毫秒数。 因此,1989年11月29日上午4:55:30在UTC中编码为“\ / Date(628318530718)\ /”。

解决办法是parsing出来:

 value = new Date(parseInt(value.replace("/Date(", "").replace(")/",""), 10)); 

不过,我听说有一个设置的地方让序列化器输出DateTime对象与new Date(xxx)语法。 我会尽力挖掘出来。


JSON.parse()的第二个参数接受一个reviver函数,其中规定了返回之前原始值是如何产生的。

这是一个date的例子:

 var parsed = JSON.parse(data, function(key, value) { if (typeof value === 'string') { var d = /\/Date\((\d*)\)\//.exec(value); return (d) ? new Date(+d[1]) : value; } return value; }); 

查看JSON.parse()的文档

这里是我的JavaScript解决scheme – 非常像JPot的,但更短(可能快一点点):

 value = new Date(parseInt(value.substr(6))); 

“value.substr(6)”取出“/ Date(”部分,parseInt函数忽略最后出现的非数字字符。

编辑:我有意遗漏了基数(第二个参数parseInt); 看到我下面的评论 。 另外请注意,ISO-8601的date优于这种旧的格式 – 所以这种格式通常不应该用于新的开发。 查看优秀的Json.NET库,以便使用ISO-8601格式序列化date。

对于ISO-8601格式化的JSONdate,只需将该string传递给Date构造函数:

 var date = new Date(jsonDate); //no ugly parsing needed; full timezone support 

处理客户端有相当多的答案,但是你可以根据需要更改输出服务器端。

有几种方法可以解决这个问题,我将从基础开始。 你必须inheritanceJsonResult类并重写ExecuteResult方法。 从那里你可以采取一些不同的方法来改变序列化。

方法1:默认实现使用JsonScriptSerializer 。 如果您查看文档,可以使用RegisterConverters方法添加自定义JavaScriptConverters 。 这个问题有几个问题:JavaScriptConverter序列化为一个字典,即它需要一个对象并序列化为一个Json字典。 为了使对象序列化到一个string,它需要一些hackery,请参阅后 。 这个特定的黑客也将逃避string。

 public class CustomJsonResult : JsonResult { private const string _dateFormat = "yyyy-MM-dd HH:mm:ss"; public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } HttpResponseBase response = context.HttpContext.Response; if (!String.IsNullOrEmpty(ContentType)) { response.ContentType = ContentType; } else { response.ContentType = "application/json"; } if (ContentEncoding != null) { response.ContentEncoding = ContentEncoding; } if (Data != null) { JavaScriptSerializer serializer = new JavaScriptSerializer(); // Use your custom JavaScriptConverter subclass here. serializer.RegisterConverters(new JavascriptConverter[] { new CustomConverter }); response.Write(serializer.Serialize(Data)); } } } 

方法2(推荐):第二种方法是从重写的JsonResult开始,并使用另一个Json序列化程序,在我的情况下是Json.NET序列化程序。 这不需要方法1的hackery。下面是我的JsonResult子类的实现:

 public class CustomJsonResult : JsonResult { private const string _dateFormat = "yyyy-MM-dd HH:mm:ss"; public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } HttpResponseBase response = context.HttpContext.Response; if (!String.IsNullOrEmpty(ContentType)) { response.ContentType = ContentType; } else { response.ContentType = "application/json"; } if (ContentEncoding != null) { response.ContentEncoding = ContentEncoding; } if (Data != null) { // Using Json.NET serializer var isoConvert = new IsoDateTimeConverter(); isoConvert.DateTimeFormat = _dateFormat; response.Write(JsonConvert.SerializeObject(Data, isoConvert)); } } } 

用法示例:

 [HttpGet] public ActionResult Index() { return new CustomJsonResult { Data = new { users=db.Users.ToList(); } }; } 

额外的学分: 詹姆斯·牛顿 – 金

Moment.js是一个广泛的date时间库,也支持这一点。 http://momentjs.com/docs/#/parsing/asp-net-json-dates/

ex:moment(“/ Date(1198908717056-0700)/”)

这可能有帮助。 擒抱输出

使用jQuery自动转换date$.parseJSON

注意 :这个答案提供了一个jQuery扩展,增加了自动的ISO和.netdate格式支持。

由于你使用的是Asp.net MVC,我怀疑你在客户端使用jQuery。 我build议你阅读这个博客文章 ,有代码如何使用$.parseJSON自动转换为您的date。

代码支持Asp.net格式化的date,就像你提到的date以及ISO格式的date。 所有date将通过使用$.parseJSON()自动格式化。

客户端和服务器之间的Ajax通信通常涉及JSON格式的数据。 虽然JSON适用于string,数字和布尔值,但是由于ASP.NET对它们进行序列化,它可能会给date带来一些困难。 由于它没有任何date的特殊表示,所以它们被序列化为纯string。 作为解决scheme,ASP.NET Web窗体和MVC的默认序列化机制以特殊forms – / Date(ticks)/ – 序列化date,其中ticks是1970年1月1日以来的毫秒数。

这个问题可以用两种方法来解决:

客户端

将接收到的datestring转换为数字,并使用date类的构造函数创build一个date对象,并使用ticks作为参数。

 function ToJavaScriptDate(value) { var pattern = /Date\(([^)]+)\)/; var results = pattern.exec(value); var dt = new Date(parseFloat(results[1])); return (dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear(); 

}

服务器端

以前的解决scheme使用客户端脚本将date转换为JavaScript Date对象。 您也可以使用以您select的格式序列化.NET DateTime实例的服务器端代码。 为了完成这个任务,你需要创build你自己的ActionResult,然后以你想要的方式序列化数据。

参考: http : //www.developer.com/net/dealing-with-json-dates-in-asp.net-mvc.html

我发现创build一个新的JsonResult并返回这是不令人满意的 – 必须replace所有调用return Json(obj) return new MyJsonResult { Data = obj }是一个痛苦。


所以我想,为什么不使用ActionFilter劫持JsonResult

 public class JsonNetFilterAttribute : ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext filterContext) { if (filterContext.Result is JsonResult == false) { return; } filterContext.Result = new JsonNetResult( (JsonResult)filterContext.Result); } private class JsonNetResult : JsonResult { public JsonNetResult(JsonResult jsonResult) { this.ContentEncoding = jsonResult.ContentEncoding; this.ContentType = jsonResult.ContentType; this.Data = jsonResult.Data; this.JsonRequestBehavior = jsonResult.JsonRequestBehavior; this.MaxJsonLength = jsonResult.MaxJsonLength; this.RecursionLimit = jsonResult.RecursionLimit; } public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } var isMethodGet = string.Equals( context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase); if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && isMethodGet) { throw new InvalidOperationException( "GET not allowed! Change JsonRequestBehavior to AllowGet."); } var response = context.HttpContext.Response; response.ContentType = string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType; if (this.ContentEncoding != null) { response.ContentEncoding = this.ContentEncoding; } if (this.Data != null) { response.Write(JsonConvert.SerializeObject(this.Data)); } } } } 

这可以应用于任何返回JsonResult使用JSON.Net的方法:

 [JsonNetFilter] public ActionResult GetJson() { return Json(new { hello = new Date(2015, 03, 09) }, JsonRequestBehavior.AllowGet) } 

这将回应

 {"hello":"2015-03-09T00:00:00+00:00"} 

如预期的!


你可以,如果你不介意在每个请求中调用比较,那么把它添加到你的FilterConfig

 // ... filters.Add(new JsonNetFilterAttribute()); 

所有的JSON现在都将被JSON.Net序列化,而不是内置的JavaScriptSerializer

我有同样的问题,而不是返回实际的date值,我只是使用ToString(“dd MMM yyyy”)就可以了。 然后在我的JavaScript我用新的date(datevalue),其中datevalue可能是“2009年1月1日”。

看到这个线程:

http://forums.asp.net/p/1038457/1441866.aspx#1441866

基本上,虽然Date()格式是有效的JavaScript,它是不是有效的JSON(有区别)。 如果你想使用旧的格式,你可能需要创build一个Facade并自己转换值,或者find一种方法在JsonResult中获得你的types的序列化器,并使用自定义date格式。

不是最优雅的方式,但这对我工作:

 var ms = date.substring(6, date.length - 2); var newDate = formatDate(ms); function formatDate(ms) { var date = new Date(parseInt(ms)); var hour = date.getHours(); var mins = date.getMinutes() + ''; var time = "AM"; // find time if (hour >= 12) { time = "PM"; } // fix hours format if (hour > 12) { hour -= 12; } else if (hour == 0) { hour = 12; } // fix minutes format if (mins.length == 1) { mins = "0" + mins; } // return formatted date time string return date.getMonth() + 1 + "/" + date.getDate() + "/" + date.getFullYear() + " " + hour + ":" + mins + " " + time; } 

我一直在解决这个问题,因为上述答案都没有帮助我。 我正在与jquery周日历和需要我的date在服务器上和本地页面上的时区信息。 经过相当多的挖掘,我find了一个解决scheme,可以帮助别人。

我使用的是asp.net 3.5,vs 2008,asp.net MVC 2和jquery周历,

首先,我使用Steven Levithan编写的图书馆,帮助处理客户端的date , Steven Levithan的date库 。 isoUtcDateTime格式非常适合我所需要的。 在我的jQuery AJAX调用中,我使用isoUtcDateTime格式库提供的格式函数,当ajax调用命中我的action方法时,datetime Kind设置为local,并反映服务器时间。

当我通过AJAX发送date到我的页面时,通过使用“ddd,dd MMM yyyy HH”:'mm':'ss'GMT'zzzz“格式化date,我将它们作为文本string发送。 这种格式很容易转换为客户端使用

 var myDate = new Date(myReceivedDate); 

这是我完整的解决scheme减去史蒂夫Levithan的来源,你可以下载:

控制器:

 public class HomeController : Controller { public const string DATE_FORMAT = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'zzzz"; public ActionResult Index() { ViewData["Message"] = "Welcome to ASP.NET MVC!"; return View(); } public ActionResult About() { return View(); } public JsonResult GetData() { DateTime myDate = DateTime.Now.ToLocalTime(); return new JsonResult { Data = new { myDate = myDate.ToString(DATE_FORMAT) } }; } public JsonResult ReceiveData(DateTime myDate) { return new JsonResult { Data = new { myDate = myDate.ToString(DATE_FORMAT) } }; } } 

使用Javascript:

 <script type="text/javascript"> function getData() { $.ajax({ url: "/Home/GetData", type: "POST", cache: "false", dataType: "json", success: function(data) { alert(data.myDate); var newDate = cleanDate(data.myDate); alert(newDate); sendData(newDate); } }); } function cleanDate(d) { if (typeof d == 'string') { return new Date(d) || Date.parse(d) || new Date(parseInt(d)); } if (typeof d == 'number') { return new Date(d); } return d; } function sendData(newDate) { $.ajax({ url: "/Home/ReceiveData", type: "POST", cache: "false", dataType: "json", data: { myDate: newDate.format("isoUtcDateTime") }, success: function(data) { alert(data.myDate); var newDate = cleanDate(data.myDate); alert(newDate); } }); } // bind myButton click event to call getData $(document).ready(function() { $('input#myButton').bind('click', getData); }); </script> 

我希望这个快速示例可以帮助其他人解决与我处于同一个问题的情况。目前,它似乎可以很好地与Microsoft JSON序列化结合使用,并可以在不同的时区保持我的date正确。

在查询中格式化date。

 var _myModel = from _m in model.ModelSearch(word) select new { date = ((DateTime)_m.Date).ToShortDateString() }; 

此解决scheme的唯一问题是,如果任何date值为空,则不会得到任何结果。 为了解决这个问题,你可以在你的查询中添加条件语句,然后再select忽略date空值的date,或者你可以设置一个查询来获得所有的结果,然后使用foreach循环遍历所有的信息,并赋值到所有date是null之前,你做你的select新。

两者的例子:

 var _test = from _t in adc.ItemSearchTest(word) where _t.Date != null select new { date = ((DateTime)_t.Date).ToShortDateString() }; 

第二个选项完全需要另一个查询,因此您可以将值分配给所有空值。 这和foreach循环必须在查询之前select值。

 var _testA = from _t in adc.ItemSearchTest(word) select _i; foreach (var detail in _testA) { if (detail.Date== null) { detail.Date= Convert.ToDateTime("1/1/0001"); } } 

只是一个想法,我发现比所有的JavaScript例子更容易。

你可以使用这个方法:

 String.prototype.jsonToDate = function(){ try{ var date; eval(("date = new " + this).replace(/\//g,'')); return date; } catch(e){ return new Date(0); } }; 

在knockoutjs中处理date的更好的方法是使用时间库和处理像老板的date。 您可以轻松处理/ Date(-62135578800000)/等date。 不需要打扰你的控制器序列化date。

 function jsonToDate(date,format) { return moment(date).format(format); } 

像使用它

 var formattedDate = jsonToDate(date,'MM/DD/YYYY') 

momentjs在date支持大量的date时间格式和实用程序function。

在你的页面中添加jQuery UI插件。

 function JsonDateFormate(dateFormate, jsonDateTime) { return $.datepicker.formatDate(dateFormate, eval('new ' + jsonDateTime.slice(1, -1))); }; 

它返回服务器date格式。 你需要定义你自己的function。

 function jsonDateFormat(jsonDate) { // Changed data format; return (new Date(parseInt(jsonDate.substr(6)))).format("mm-dd-yyyy / h:MM tt"); 

};

这是我写的一些JavaScript代码,它从ASP.NET MVC传递的date中设置了一个<input type="date">值。

  var setDate = function (id, d) { if (d !== undefined && d !== null) { var date = new Date(parseInt(d.replace("/Date(", "").replace(")/", ""), 10)); var day = ('0' + date.getDate()).slice(-2); var month = ('0' + (date.getMonth() + 1)).slice(-2); var parsedDate = date.getFullYear() + "-" + (month) + "-" + (day); $(id).val(parsedDate); } }; 

你可以这样调用这个函数:

 setDate('#productCommissionStartDate', data.commissionStartDate); 

其中commissionStartDate是MVC传递的JSONdate。

不是没有,但有另一种方式。 首先,构build你的LINQ查询。 然后,构造Enumerated结果的查询并为您应用任何types的格式化工作。

 var query = from t in db.Table select new { t.DateField }; var result = from c in query.AsEnumerable() select new { c.DateField.toString("dd MMM yyy") }; 

我不得不说,额外的步骤是烦人的,但它很好地工作。

什么对我来说是创build一个包含date属性作为一个string的视图模型。 从域模型分配DateTime属性,并在将值赋给viewmodel的同时调用date属性的.ToString()。

MVC操作方法的JSON结果将以与视图兼容的格式返回date。

查看模型

 public class TransactionsViewModel { public string DateInitiated { get; set; } public string DateCompleted { get; set; } } 

领域模型

 public class Transaction{ public DateTime? DateInitiated {get; set;} public DateTime? DateCompleted {get; set;} } 

控制器操作方法

 public JsonResult GetTransactions(){ var transactions = _transactionsRepository.All; var model = new List<TransactionsViewModel>(); foreach (var transaction in transactions) { var item = new TransactionsViewModel { ............... DateInitiated = transaction.DateInitiated.ToString(), DateCompleted = transaction.DateCompleted.ToString(), }; model.Add(item); } return Json(model, JsonRequestBehavior.AllowGet); } 

覆盖控制器Json / JsonResult返回JSON.Net:

这是一种享受

讨厌,不是吗?

我的解决scheme是改变我的WCF服务,让它以更可读的(非微软)格式返回DateTimes。 请注意下面的“ UpdateDateOriginal ”,它是WCF默认的date格式,我的“ UpdateDate ”格式化为更可读的格式。

在这里输入图像描述

以下是如何做到这一点:

更改WCFdate格式

希望这可以帮助。