この記事では主に Json日付形式の問題に対する 4 つの解決策を紹介します。非常に優れており、必要な友人は参考にしてください。
開発中にサーバーから 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();</student></student>
実行結果は次のとおりです:
対応するトムの誕生日「2014-01-31」は 1391141532000 となり、これは実際には 1970 年 1 月 1 日から現在までのミリ秒数です。1391141532000/1000/60/60/24/365=44.11 years, 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; } } } }
再投影するメソッドを選択オブジェクトのコレクションと誕生日の変更 属性は新しい属性に変換されます。属性を変更した後は、属性名を同じにする必要があることに注意してください。または、同じ目的を達成するために他の方法を選択することもできます。この方法では、クライアントによって使用されない属性をコレクションから削除して、単にパフォーマンスを最適化するという目的を達成できます。 実行結果:
この時の日付形式はわかりやすい形式になっていますが、JavaScriptではこれは単なる文字列です。
方法2:「Birthday」:"/Date(1391141532000)/"の文字列をJavaScriptの日付オブジェクトに変換する 数値以外の文字に対応するValueの誕生日
キーを変換できます。数値が 1391141532000 になるまで置換によって削除され、JavaScript で日付オブジェクトを取得するパラメータとして 1391141532000 ミリ秒を使用して Date オブジェクトがインスタンス化されます。 コードは次のとおりです。 <!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 は、それぞれ大文字と小文字を無視 (無視) することを意味します。 -line replace (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 は合理的または十分強力ではない可能性があるため、変更できます。必要に応じて。
方法 3:いくつかのサードパーティ JSON ツール クラスを選択できます。その多くはすでに日付形式の問題に対処しています。一般的な
json シリアル化および逆シリアル化ツール ライブラリは次のとおりです。 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-json11.Manatee Json
ここでは、json のシリアル化と逆シリアル化の例として litjson が使用されています。コードは次のとおりです。
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; } } } }
日付この時点での形式は基本的に正しいです。
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());
方法 4:
这点文字发到博客上有网友提出了他们宝贵的意见,我并没有考虑在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つの解決策を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。