1. 程式人生 > >4種解決json日期格式問題的辦法

4種解決json日期格式問題的辦法

開發中有時候需要從伺服器端返回json格式的資料,在後臺程式碼中如果有DateTime型別的資料使用系統自帶的工具類序列化後將得到一個很長的數字表示日期資料,如下所示:

           //設定伺服器響應的結果為純文字格式
            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 日至今的毫秒數;1391141532000/1000/60/60/24/365=44.11年,44+1970=2014年,按這種方法可以得出年月日時分秒和毫秒。這種格式是一種可行的表示形式但不是普通人可以看懂的友好格式,怎麼讓這個格式變化?

解決辦法:

方法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查詢表示式,也可以選擇別的方式達到相同的目的;這種辦法可以將集合中客戶端不用的屬性剔除,達到簡單優化效能的目的。

執行結果:

這時候的日期格式就已經變成友好格式了,不過在javascript中這只是一個字串。

方法二:

在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小時制。另外還有幾個問題要問大家:

1、通過Reflector反編譯得到的程式碼中有很多變化,如屬性會變成get_Request()方法的形式,不知道大家有沒有更好的方法。

2、在反編譯得到的程式碼中使用到了資原始檔MvcResources.JsonRequest_GetNotAllowed,怎麼在重寫時也可以使用?

這裡講到了幾種解決json中序列化後的日期格式問題,應該還有更好更完善的方法,歡迎您告訴我。因為有很多學生問我所以我寫了這點文字,歡迎批評指正。

相關推薦

4解決json日期格式問題的辦法

開發中有時候需要從伺服器端返回json格式的資料,在後臺程式碼中如果有DateTime型別的資料使用系統自帶的工具類序列化後將得到一個很長的數字表示日期資料,如下所示: //設定伺服器響應的結果為純文字格式 context.Response.Content

使用newtonjson解決Json日期格式問題

encoding ignorecas ati align cti val tpm ride serial 使用Json.Net代替最簡單的方法就是使用下面的JsonNetResult 來作為 ActionResult返回。 但是比較麻煩,還有很多其他方法。下面使用我研究的最

針對兩不同的日期格式進行轉成年月日時分秒的格式

provide mes nbsp code oba cnblogs -m bsp class 有兩個時間字符串,格式分別是 string dateEnglish = "1-6-14 8:25";//格式為 月-日-年 string dateFranch = "13-1-1

json日期格式轉換為正常格式

ets 日期 gets urn second nbsp int pan bsp function jsonDateFormat(jsonDate) { try { var date = new Date(parseInt(jsonDate.repl

盤點Kubernetes網絡問題的4解決方案

driver RM 需要 企業級 ssl證書 AI 等等 docke pipe 由於在企業中部署私有雲的場景會更普遍,所以在私有雲中運行Kubernetes + Docker集群之前,就需要自己搭建符合Kubernetes要求的網絡環境。現在的開源世界裏,有很多開源組件可以

JS公用函式(1)——Json日期格式轉換

Json日期格式轉化為常用格式(YYYYMMDD): //將序列化成json格式後日期(毫秒數)轉成日期格式 function ChangeDateFormat(cellval) { if (cellval) {

eclipse中執行tomcat提示埠被佔的4解決方案

今天碰到一個問題,在eclipse中執行一個程式,eclipse裡面的tomcat一啟動就報錯說端口占用,eclipse完全不能聯網,maven不能下載依賴包,不能建立maven專案,不能安裝外掛,然後我查看了本機的端口占用情況也沒有看到我要用的埠被別的應用佔用,最後…….折騰了好久,終於弄好了,分享如下:錯

Javaweb開發關於後臺返回的json日期格式在js中時間戳轉年月日

在專案中遇到一個問題,後臺返回的json串中所有的日期都變成時間戳了 想要把它轉為年月日時分秒想了半天想出來一種辦法 function formateDate(str,symb){  symb=symb?symb:" ";  var d =new Date(str);  v

initBinder解決Json日期轉換為date型別

{‘date':’2015-01-01 00:00:00‘} 在目前springMVC3 中通過配置 annotation 註解自動封裝為javaBean 物件 <mvc:annotation-

使用poi實現java讀取excel表格並存儲到資料庫中解決讀取日期格式問題(ssm框架)

本文是在搭完ssm框架之上實現的讀取excel檔案,已實現功能,如有問題可在評論區詢問使用的jar包<!-- https://mvnrepository.com/artifact/org.apache.poi/poi --><dependency>

JQuery返回Json日期格式的問題 jquery對時間/Date(1387900800000)進行處理

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> 1 function DataBindToMemberDetailDialog(me

json日期格式轉換

       開發中,往往在後臺把帶有日期型別的一些資料直接轉成json然後繫結到前臺的樣式列表控制元件裡,在控制元件裡獲取或者繫結時,Date型別往往都變成了如 {"date":26,"day":1

JQuery返回Json日期格式的問題

用JQuery Ajax返回一個Entity的Json資料時,如果Entity的屬性中有日期格式,那返回來的是一串字串,如下圖所示:   在網上找了很久也沒有找到一個好的解決方案,最後自己寫一個javascrip Function 特此記錄,以備後用: UPDATE:可以用

盤點Kubernetes網路問題的4解決方案

由於在企業中部署私有云的場景會更普遍,所以在私有云中執行Kubernetes + Docker叢

解決帶有日期格式的txt資料匯入oracle報錯的問題

將txt匯入oracle中有兩種方法1.使用sqlloader命令匯入 需要自己編寫ctl檔案 2.txt轉excel,再匯入oracle中 剛開始我這兩種方法都試過,可是都報錯誤,就是日類型別的資料報錯,這個錯誤折磨了我兩天,具體就不多說了,直接上解決方法 由於我的系統預

實現水平垂直居中的4解決方案

1.基於表格樣式 將要使內容居中的外層容器元素的display設定成table,內層內容塊使用table-cell,然後分別設定水平和垂直居中: /*表格方案*/ #table-father{

linq中日期格式轉換或者比較,程序報錯說不支持方法的解決辦法

格式 var lec fun edi nbsp diff sql 方法 public void TestMethod1(){using (var _context = new hotelEntities()){var rq = DateTime.Now.Date;var q

python讀取excel,數字都是浮點型,日期格式是數字的解決辦法

6.2 spa 讀取excel pytho work clas odin 技術 div excel文件內容: 讀取excel: # coding=utf-8 import xlrd import sys reload(sys) sys.setdefaultenco

linux 命令行不顯示路徑了,而顯示為-bash-4.1#的兩解決辦法

技術分享 用戶家目錄 清空 目錄 RoCE color 編輯 重新 我們 問題描述: linux的命令行界面顯示的不是路徑,而是-bash-4.1#: 原因分析: 出現這個問題的原因是因為沒有配置.bash_profile的問題,或者是我們不小心清空或刪除了.bash_pr

linux 命令列不顯示路徑了,而顯示為-bash-4.1#的兩解決辦法

問題描述: linux的命令列介面顯示的不是路徑,而是-bash-4.1#: 原因分析: 出現這個問題的原因是因為沒有配置.bash_profile的問題,或者是我們不小心清空或刪除了.bash_profile檔案。 解決方法 方法一:修改 ~/.bash_profile檔案 1、修改~/.bas