Json日期格式問題的四種解決方法(超詳細)
開發(fā)中有時候需要從服務器端返回json格式的數(shù)據(jù),在后臺代碼中如果有DateTime類型的數(shù)據(jù)使用系統(tǒng)自帶的工具類序列化后將得到一個很長的數(shù)字表示日期數(shù)據(jù),如下所示:
//設置服務器響應的結果為純文本格式
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();
運行結果是:

其中Tom所對應生日“2014-01-31”變成了1391141532000,這其實是1970 年 1 月 1 日至今的毫秒數(shù);1391141532000/1000/60/60/24/365=44.11年,44+1970=2014年,按這種方法可以得出年月日時分秒和毫秒。這種格式是一種可行的表示形式但不是普通人可以看懂的友好格式,怎么讓這個格式變化?
解決辦法:
方法1:在服務器端將日期格式使用Select方法或LINQ表達式轉換后發(fā)到客戶端:
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屬性轉換成一個新的屬性
//注意屬性變化后要重新命名,并立即執(zhí)行
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查詢表達式,也可以選擇別的方式達到相同的目的;這種辦法可以將集合中客戶端不用的屬性剔除,達到簡單優(yōu)化性能的目的。
運行結果:

這時候的日期格式就已經變成友好格式了,不過在javascript中這只是一個字符串。
方法二:
在javascript中將"Birthday":"\/Date(1391141532000)\/"中的字符串轉換成javascript中的日期對象,可以將Birthday這個Key所對應的Value中的非數(shù)字字符以替換的方式刪除,到到一個數(shù)字1391141532000,然后實例化一個Date對象,將1391141532000毫秒作為參數(shù),得到一個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");
//使用正則表達式將生日屬性中的非數(shù)字(\D)刪除
//并把得到的毫秒數(shù)轉換成數(shù)字類型
var birthdayMilliseconds = parseInt(obj.Birthday.replace(/\D/igm, ""));
//實例化一個新的日期格式,使用1970 年 1 月 1 日至今的毫秒數(shù)為參數(shù)
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達到替換所有非數(shù)字的目的,\D表示非數(shù)字,igm是參數(shù),分別表示忽視(ignore)大小寫;多次、全局(global)替換;多行替換(multi-line);有一些時候還會出現(xiàn)+86的情況,只需要變換正則同樣可以達到目的。另外如果項目中反復出現(xiàn)這種需要處理日期格式的問題,可以擴展一個javascript方法,代碼如下:
$(function () {
$.getJSON("getJson.ashx", function (students) {
$.each(students, function (index, obj) {
$("<li/>").html(obj.Name).appendTo("#ulStudents");
//使用正則表達式將生日屬性中的非數(shù)字(\D)刪除
//并把得到的毫秒數(shù)轉換成數(shù)字類型
var birthdayMilliseconds = parseInt(obj.Birthday.replace(/\D/igm, ""));
//實例化一個新的日期格式,使用1970 年 1 月 1 日至今的毫秒數(shù)為參數(shù)
var birthday = new Date(birthdayMilliseconds);
$("<li/>").html(birthday.toLocaleString()).appendTo("#ulStudents");
$("<li/>").html(obj.Birthday.toDate()).appendTo("#ulStudents");
});
});
});
//在String對象中擴展一個toDate方法,可以根據(jù)要求完善
String.prototype.toDate = function () {
var dateMilliseconds;
if (isNaN(this)) {
//使用正則表達式將日期屬性中的非數(shù)字(\D)刪除
dateMilliseconds =this.replace(/\D/igm, "");
} else {
dateMilliseconds=this;
}
//實例化一個新的日期格式,使用1970 年 1 月 1 日至今的毫秒數(shù)為參數(shù)
return new Date(parseInt(dateMilliseconds));
};
上面擴展的方法toDate不一定合理,也不夠強大,可以根據(jù)需要修改。
方法三:
可以選擇一些第三方的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());
方法四:
這點文字發(fā)到博客上有網友提出了他們寶貴的意見,我并沒有考慮在MVC中的情況,其實MVC中也可以使用handler,所以區(qū)別不是很大了,但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是有區(qū)別的,如這里表示時間的H如果大寫表示24小時制,如果小寫表示12小時制。另外還有幾個問題要問大家:
1、通過Reflector反編譯得到的代碼中有很多變化,如屬性會變成get_Request()方法的形式,不知道大家有沒有更好的方法。
2、在反編譯得到的代碼中使用到了資源文件MvcResources.JsonRequest_GetNotAllowed,怎么在重寫時也可以使用?
以上所述是小編給大家介紹的Json日期格式問題的四種解決方法小結(超詳細),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!
相關文章
詳解ASP.NET-----Repeater數(shù)據(jù)控件的用法總結
本篇文章主要介紹了ASP.NET--Repeater數(shù)據(jù)控件的用法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。2016-11-11
ASP.NET中Response.BufferOutput屬性的使用技巧
這篇文章介紹了ASP.NET中Response.BufferOutput屬性的使用技巧,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07
在 .NET Framework 2.0 中未處理的異常導致基于 ASP.NET 的應用程序意外退出
如果在 Microsoft .NET Framework 2.0 上構建的基于 Microsoft ASP.NET 的應用程序中引發(fā)未處理的異常,該應用程序將會意外退出。如果出現(xiàn)這個問題,不會在應用程序日志中記錄了解此問題所必需的異常信息。2009-11-11

