开发中有时候须要从服务器端返回json格式的数据,在后台代码中若是有DateTime类型的数据使用系统自带的工具类序列化后将获得一个很长的数字表示日期数据,以下所示:javascript
//设置服务器响应的结果为纯文本格式 context.Response.ContentType = "text/plain"; //学生对象集合 List<Student> students = new List<Student> { new Student(){Name ="Tom", Birthday =Convert.ToDateTime("2014-01-31 12:12:12")}, new Student(){Name ="Rose", Birthday =Convert.ToDateTime("2014-01-10 11:12:12")}, new Student(){Name ="Mark", Birthday =Convert.ToDateTime("2014-01-09 10:12:12")} }; //javascript序列化器 JavaScriptSerializer jss=new JavaScriptSerializer(); //序列化学生集合对象获得json字符 string studentsJson=jss.Serialize(students); //将字符串响应到客户端 context.Response.Write(studentsJson); context.Response.End();
运行结果是:html
其中Tom所对应生日“2014-01-31”变成了1391141532000,这实际上是1970 年 1 月 1 日至今的毫秒数;1391141532000/1000/60/60/24/365=44.11年,44+1970=2014年,按这种方法能够得出年月日时分秒和毫秒。这种格式是一种可行的表示形式但不是普通人能够看懂的友好格式,怎么让这个格式变化?java
解决办法:jquery
方法1:在服务器端将日期格式使用Select方法或LINQ表达式转换后发到客户端:正则表达式
using System; using System.Collections.Generic; using System.Web; using System.Web.Script.Serialization; namespace JsonDate1 { using System.Linq; /// <summary> /// 学生类,测试用 /// </summary> public class Student { /// <summary> /// 姓名 /// </summary> public String Name { get; set; } /// <summary> /// 生日 /// </summary> public DateTime Birthday { get; set; } } /// <summary> /// 返回学生集合的json字符 /// </summary> public class GetJson : IHttpHandler { public void ProcessRequest(HttpContext context) { //设置服务器响应的结果为纯文本格式 context.Response.ContentType = "text/plain"; //学生对象集合 List<Student> students = new List<Student> { new Student(){Name ="Tom",Birthday =Convert.ToDateTime("2014-01-31 12:12:12")}, new Student(){Name ="Rose",Birthday =Convert.ToDateTime("2014-01-10 11:12:12")}, new Student(){Name ="Mark",Birthday =Convert.ToDateTime("2014-01-09 10:12:12")} }; //使用Select方法从新投影对象集合将Birthday属性转换成一个新的属性 //注意属性变化后要从新命名,并当即执行 var studentSet = students.Select ( p => new { p.Name, Birthday = p.Birthday.ToString("yyyy-mm-dd") } ).ToList(); //javascript序列化器 JavaScriptSerializer jss = new JavaScriptSerializer(); //序列化学生集合对象获得json字符 string studentsJson = jss.Serialize(studentSet); //将字符串响应到客户端 context.Response.Write(studentsJson); context.Response.End(); } public bool IsReusable { get { return false; } } } }
Select方法从新投影对象集合将Birthday属性转换成一个新的属性,注意属性变化后要从新命名,属性名能够相同;这里可使用select方法也可使用LINQ查询表达式,也能够选择别的方式达到相同的目的;这种办法能够将集合中客户端不用的属性剔除,达到简单优化性能的目的。json
运行结果:服务器
这时候的日期格式就已经变成友好格式了,不过在javascript中这只是一个字符串。app
方法二:ide
在javascript中将"Birthday":"\/Date(1391141532000)\/"中的字符串转换成javascript中的日期对象,能够将Birthday这个Key所对应的Value中的非数字字符以替换的方式删除,到到一个数字1391141532000,而后实例化一个Date对象,将1391141532000毫秒做为参数,获得一个javascript中的日期对象,代码以下:工具
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>json日期格式处理</title> <script src="Scripts/jquery-1.10.2.min.js" type="text/javascript"></script> <script type="text/javascript"> $(function() { $.getJSON("getJson.ashx", function (students) { $.each(students, function (index, obj) { $("<li/>").html(obj.Name).appendTo("#ulStudents"); //使用正则表达式将生日属性中的非数字(\D)删除 //并把获得的毫秒数转换成数字类型 var birthdayMilliseconds = parseInt(obj.Birthday.replace(/\D/igm, "")); //实例化一个新的日期格式,使用1970 年 1 月 1 日至今的毫秒数为参数 var birthday = new Date(birthdayMilliseconds); $("<li/>").html(birthday.toLocaleString()).appendTo("#ulStudents"); ; }); }); }); </script> </head> <body> <h2>json日期格式处理</h2> <ul id="ulStudents"> </ul> </body> </html>
运行结果:
上的使用正则/\D/igm达到替换全部非数字的目的,\D表示非数字,igm是参数,分别表示忽视(ignore)大小写;屡次、全局(global)替换;多行替换(multi-line);有一些时候还会出现+86的状况,只须要变换正则一样能够达到目的。另外若是项目中反复出现这种须要处理日期格式的问题,能够扩展一个javascript方法,代码以下:
$(function () { $.getJSON("getJson.ashx", function (students) { $.each(students, function (index, obj) { $("<li/>").html(obj.Name).appendTo("#ulStudents"); //使用正则表达式将生日属性中的非数字(\D)删除 //并把获得的毫秒数转换成数字类型 var birthdayMilliseconds = parseInt(obj.Birthday.replace(/\D/igm, "")); //实例化一个新的日期格式,使用1970 年 1 月 1 日至今的毫秒数为参数 var birthday = new Date(birthdayMilliseconds); $("<li/>").html(birthday.toLocaleString()).appendTo("#ulStudents"); $("<li/>").html(obj.Birthday.toDate()).appendTo("#ulStudents"); }); }); }); //在String对象中扩展一个toDate方法,能够根据要求完善 String.prototype.toDate = function () { var dateMilliseconds; if (isNaN(this)) { //使用正则表达式将日期属性中的非数字(\D)删除 dateMilliseconds =this.replace(/\D/igm, ""); } else { dateMilliseconds=this; } //实例化一个新的日期格式,使用1970 年 1 月 1 日至今的毫秒数为参数 return new Date(parseInt(dateMilliseconds)); };
上面扩展的方法toDate不必定合理,也不够强大,能够根据须要修改。
方法三:
能够选择一些第三方的json工具类,其中不乏有一些已经对日期格式问题已处理好了的,常见的json序列化与反序列化工具库有:
1.fastJSON.
2.JSON_checker.
3.Jayrock.
4.Json.NET - LINQ to JSON.
5.LitJSON.
6.JSON for .NET.
7.JsonFx.
8.JSONSharp.
9.JsonExSerializer.
10.fluent-json
11.Manatee Json
这里以litjson为序列化与反序列化json的工具类做示例,代码以下:
using System; using System.Collections.Generic; using System.Web; using LitJson; namespace JsonDate2 { using System.Linq; /// <summary> /// 学生类,测试用 /// </summary> public class Student { /// <summary> /// 姓名 /// </summary> public String Name { get; set; } /// <summary> /// 生日 /// </summary> public DateTime Birthday { get; set; } } /// <summary> /// 返回学生集合的json字符 /// </summary> public class GetJson : IHttpHandler { public void ProcessRequest(HttpContext context) { //设置服务器响应的结果为纯文本格式 context.Response.ContentType = "text/plain"; //学生对象集合 List<Student> students = new List<Student> { new Student(){Name ="Tom",Birthday =Convert.ToDateTime("2014-01-31 12:12:12")}, new Student(){Name ="Rose",Birthday =Convert.ToDateTime("2014-01-10 11:12:12")}, new Student(){Name ="Mark",Birthday =Convert.ToDateTime("2014-01-09 10:12:12")} }; //序列化学生集合对象获得json字符 string studentsJson = JsonMapper.ToJson(students); //将字符串响应到客户端 context.Response.Write(studentsJson); context.Response.End(); } public bool IsReusable { get { return false; } } } }
运行结果以下:
这时候的日期格式就基本正确了,只要在javascript中直接实例化日期就行了,
var date = new Date("01/31/2014 12:12:12");
alert(date.toLocaleString());
客户端的代码以下:
$(function () { $.getJSON("GetJson2.ashx", function (students) { $.each(students, function (index, obj) { $("<li/>").html(obj.Name).appendTo("#ulStudents"); var birthday = new Date(obj.Birthday); $("<li/>").html(birthday.toLocaleString()).appendTo("#ulStudents"); }); }); }); var date = new Date("01/31/2014 12:12:12"); alert(date.toLocaleString());
方法四:
这点文字发到博客上有网友提出了他们宝贵的意见,我并无考虑在MVC中的状况,其实MVC中也可使用handler,因此区别不是很大了,但MVC中有专门针对服务器响应为JSON的Action,代码以下:
using System; using System.Web.Mvc; namespace JSONDateMVC.Controllers { public class HomeController : Controller { public JsonResult GetJson1() { //序列化当前日期与时间对象,并容许客户端Get请求 return Json(DateTime.Now, JsonRequestBehavior.AllowGet); } } }
运行结果:
下载一个内容为Application/json的文件,文件名为GetJson1,内容是"\/Date(1391418272884)\/"
从上面的状况看来MVC中序列化时并未对日期格式特别处理,咱们能够反编译看源码:
Return调用的Json方法:
protected internal JsonResult Json(object data, JsonRequestBehavior behavior) { return this.Json(data, null, null, behavior); }
this.Json方法
protected internal virtual JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior) { return new JsonResult { Data = data, ContentType = contentType, ContentEncoding = contentEncoding, JsonRequestBehavior = behavior }; }
JsonResult类ActionResult类的子类,ExecuteResult方法:
从上面的代码中不难看出微软的JsonResult类仍然是使用了JavaScriptSerializer,因此返回的结果与方法一未处理时是同样的,要解决这个问题咱们能够派生出一个新的类,重写ExecuteResult方法,使用Json.net来完成序列化工做,JsonResultPro.cs文件的代码以下:
namespace JSONDateMVC.Common { using System; using System.Web; using System.Web.Mvc; using Newtonsoft.Json; using Newtonsoft.Json.Converters; public class JsonResultPro : JsonResult { public JsonResultPro(){} public JsonResultPro(object data, JsonRequestBehavior behavior) { base.Data = data; base.JsonRequestBehavior = behavior; this.DateTimeFormat = "yyyy-MM-dd hh:mm:ss"; } public JsonResultPro(object data, String dateTimeFormat) { base.Data = data; base.JsonRequestBehavior = JsonRequestBehavior.AllowGet; this.DateTimeFormat = dateTimeFormat; } /// <summary> /// 日期格式 /// </summary> public string DateTimeFormat{ get; set; } public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } if ((this.JsonRequestBehavior == JsonRequestBehavior.DenyGet) && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("MvcResources.JsonRequest_GetNotAllowed"); } HttpResponseBase base2 = context.HttpContext.Response; if (!string.IsNullOrEmpty(this.ContentType)) { base2.ContentType = this.ContentType; } else { base2.ContentType = "application/json"; } if (this.ContentEncoding != null) { base2.ContentEncoding = this.ContentEncoding; } if (this.Data != null) { //转换System.DateTime的日期格式到 ISO 8601日期格式 //ISO 8601 (如2008-04-12T12:53Z) IsoDateTimeConverter isoDateTimeConverter=new IsoDateTimeConverter(); //设置日期格式 isoDateTimeConverter.DateTimeFormat = DateTimeFormat; //序列化 String jsonResult = JsonConvert.SerializeObject(this.Data,isoDateTimeConverter); //相应结果 base2.Write(jsonResult); } } } }
使用上面的JsonResultPro Action类型的代码以下:
public JsonResultPro GetJson2() { //序列化当前日期与时间对象,并容许客户端Get请求,注意H是大写 return new JsonResultPro(DateTime.Now,"yyyy-MM-dd HH:mm"); }
运行结果:
"2014-02-03 18:10"
这样就能够彻底按本身的意思来设置日期格式了,但须要注意日期格式如平时的Format是有区别的,如这里表示时间的H若是大写表示24小时制,若是小写表示12小时制。另外还有几个问题要问你们:
一、经过Reflector反编译获得的代码中有不少变化,如属性会变成get_Request()方法的形式,不知道你们有没有更好的方法。
二、在反编译获得的代码中使用到了资源文件MvcResources.JsonRequest_GetNotAllowed,怎么在重写时也可使用?
这里讲到了几种解决json中序列化后的日期格式问题,应该还有更好更完善的方法,欢迎您告诉我。由于有不少学生问我因此我写了这点文字,欢迎批评指正。
转自:张果老师 原文地址: http://www.cnblogs.com/best/p/3537030.html