超高性能的json序列化之MVC中使用Json.Net

先不廢話,直接上代碼json

Asp.net MVC自帶Json序列化app

 1 /// <summary>
 2 /// 加載組件列表
 3 /// </summary>
 4 /// <param name="departmentId">做業部/廠</param>
 5 /// <param name="unitId">組件Id</param>
 6 /// <param name="tag">標籤號</param>
 7 /// <param name="pageIndex">當前頁碼</param>
 8 /// <param name="pageSize">每頁條數</param>
 9 /// <returns>返回組件json數據</returns>
10 public JsonResult ListCom(long departmentId, IEnumberable<long> unitIds, string tag, int pageIndex, int pageSize)
11 {
12     var dataEntity = LdarService.ListCom(unitIds, tag, pageIndex + 1, pageSize);
13     var dataModel = new Page<LdComModel> {Total = dataEntity.Total};
14     var data =
15         dataModel.DataList =
16             dataEntity.DataList.Select(model => Builder.Builder.Convert<LdComModel>(new object[] {model}));//Entity轉ViewModel
17     dataModel.DataList = data;
18     return Json(new {
19             msg = CommonModelBuilder.BuildQuerySuccessMessage("組件信息維護", (int) dataModel.Total),
20             data = dataModel.DataList,
21             total = dataModel.Total
22         });
23 }
顯示到前臺界面

接收到的報文中有不少導航屬性,前臺並不須要這些屬性.

LdComModel類中關聯了不少外表,也就是導航屬性,導航也被序列化,這樣不科學,會將全部屬性包括導航屬性都序列化,還可能會形成循環引用,致使報錯。
我只想序列須要的字段,這時能夠手寫一個匿名類
1 var data=new {
2      model.AreaName,
3      model.AreaId,
4      ......                  
5 };

這麼寫字段少還好,字段多就很不爽吧。框架

這時咱們能夠用Json.Net序列化,首先引用newtonsoft.json.dll,使用nuget引用比較方便。在不想序列化的屬性上打上[JsonIgnore]特性,序列化就會被忽略。ide

LdComModel類中的部分代碼
 1 /// <summary>
 2 /// 分區
 3 /// </summary>
 4 [JsonIgnore]
 5 public LdAreaModel LdAreaModel { get; set; }
 6 
 7 /// <summary>
 8 /// 區域名稱
 9 /// </summary>
10 public string AreaName
11 {
12     get
13     {
14         return LdAreaModel.LdarAreaName;
15     }
16 }

 

使用JsonNet序列化ui

 1 /// <summary>
 2 /// 加載組件列表
 3 /// </summary>
 4 /// <param name="departmentId">做業部/廠</param>
 5 /// <param name="unitId">組件Id</param>
 6 /// <param name="tag">標籤號</param>
 7 /// <param name="pageIndex">當前頁碼</param>
 8 /// <param name="pageSize">每頁條數</param>
 9 /// <returns>返回組件json數據</returns>
10 public JsonResult ListCom(long departmentId, IEnumberable<long> unitIds, string tag, int pageIndex, int pageSize)
11 {
12     var dataEntity = LdarService.ListCom(unitIds, tag, pageIndex + 1, pageSize);
13     var dataModel = new Page<LdComModel> {Total = dataEntity.Total};
14     var data =
15         dataModel.DataList =
16             dataEntity.DataList.Select(model => Builder.Builder.Convert<LdComModel>(new object[] {model}));//Entity轉ViewModel
17     dataModel.DataList = data;
18     var result = new JsonNetResult()
19         {
20             Data = new
21             {
22                 msg = CommonModelBuilder.BuildQuerySuccessMessage("組件信息維護", (int) dataModel.Total),
23                 data = dataModel.DataList,
24                 total = dataModel.Total
25             }
26         };
27         return result;
28 }

這時返回到前臺的json中沒有多餘的導航屬性.this

導航屬性沒有被序列化,速度也快了不少。編碼

這樣寫,雖然能夠實現功能,很每次都要new一個JsonNetResult對象,寫起來非常不爽,能不能給Controller寫個擴展方法,像Json(...)同樣直接寫JsonNet(...)?spa

Controller中Json(...)方法的部分源碼.net

 1     /// <summary>
 2     /// 建立一個將指定對象序列化爲 JavaScript 對象表示法 (JSON) 的 <see cref="T:System.Web.Mvc.JsonResult"/> 對象。
 3     /// </summary>
 4     /// 
 5     /// <returns>
 6     /// 將指定對象序列化爲 JSON 格式的 JSON 結果對象。在執行此方法所準備的結果對象時,ASP.NET MVC 框架會將該對象寫入響應。
 7     /// </returns>
 8     /// <param name="data">要序列化的 JavaScript 對象圖。</param>
 9     protected internal JsonResult Json(object data)
10     {
11       return this.Json(data, (string) null, (Encoding) null, JsonRequestBehavior.DenyGet);
12     }
13 
14 // <summary>
15     /// 建立 <see cref="T:System.Web.Mvc.JsonResult"/> 對象,該對象使用內容類型、內容編碼和 JSON 請求行爲將指定對象序列化爲 JavaScript 對象表示法 (JSON) 格式。
16     /// </summary>
17     /// 
18     /// <returns>
19     /// 將指定對象序列化爲 JSON 格式的結果對象。
20     /// </returns>
21     /// <param name="data">要序列化的 JavaScript 對象圖。</param><param name="contentType">內容類型(MIME 類型)。</param><param name="contentEncoding">內容編碼。</param><param name="behavior">JSON 請求行爲</param>
22     protected internal virtual JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
23     {
24       return new JsonResult()
25       {
26         Data = data,
27         ContentType = contentType,
28         ContentEncoding = contentEncoding,
29         JsonRequestBehavior = behavior
30       };
31     }

咱們能夠仿照Controller中的源碼,本身給Controller寫個擴展方法JsonNet(...)code

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Web;
  6 
  7 namespace System.Web.Mvc
  8 {
  9     public static class ControllerExt
 10     {
 11         /// <summary>
 12         /// 建立一個將指定對象序列化爲 JavaScript 對象表示法 (JSON) 的 <see cref="T:System.Web.Mvc.JsonNetResult"/> 對象。
 13         /// </summary>
 14         /// 
 15         /// <returns>
 16         /// 將指定對象序列化爲 JSON 格式的 JSON 結果對象。在執行此方法所準備的結果對象時,ASP.NET MVC 框架會將該對象寫入響應。
 17         /// </returns>
 18         /// <param name="controller">控件器</param>
 19         /// <param name="data">要序列化的 JavaScript 對象圖。</param>
 20         public static JsonNetResult JsonNet(this Controller controller, object data)
 21         {
 22             return JsonNet(data, (string) null, (Encoding) null, JsonRequestBehavior.DenyGet);
 23         }
 24 
 25         /// <summary>
 26         /// 建立一個將指定對象序列化爲 JavaScript 對象表示法 (JSON) 格式的 <see cref="T:System.Web.Mvc.JsonNetResult"/> 對象。
 27         /// </summary>
 28         /// 
 29         /// <returns>
 30         /// 將指定對象序列化爲 JSON 格式的 JSON 結果對象。
 31         /// </returns>
 32         /// <param name="controller">控件器</param>
 33         /// <param name="data">要序列化的 JavaScript 對象圖。</param>
 34         /// <param name="contentType">內容類型(MIME 類型)。</param>
 35         public static JsonNetResult JsonNet(this Controller controller, object data, string contentType)
 36         {
 37             return JsonNet(data, contentType, (Encoding) null, JsonRequestBehavior.DenyGet);
 38         }
 39 
 40         /// <summary>
 41         /// 建立一個將指定對象序列化爲 JavaScript 對象表示法 (JSON) 格式的 <see cref="T:System.Web.Mvc.JsonNetResult"/> 對象。
 42         /// </summary>
 43         /// 
 44         /// <returns>
 45         /// 將指定對象序列化爲 JSON 格式的 JSON 結果對象。
 46         /// </returns>
 47         /// <param name="controller">控件器</param>
 48         /// <param name="data">要序列化的 JavaScript 對象圖。</param>
 49         /// <param name="contentType">內容類型(MIME 類型)。</param>
 50         /// <param name="contentEncoding">內容編碼。</param>
 51         public static JsonNetResult JsonNet(this Controller controller, object data, string contentType,
 52             Encoding contentEncoding)
 53         {
 54             return JsonNet(data, contentType, contentEncoding, JsonRequestBehavior.DenyGet);
 55         }
 56 
 57         /// <summary>
 58         /// 建立 <see cref="T:System.Web.Mvc.JsonNetResult"/> 對象,該對象使用指定 JSON 請求行爲將指定對象序列化爲 JavaScript 對象表示法 (JSON) 格式。
 59         /// </summary>
 60         /// 
 61         /// <returns>
 62         /// 將指定對象序列化爲 JSON 格式的結果對象。
 63         /// </returns>
 64         /// <param name="controller">控件器</param>
 65         /// <param name="data">要序列化的 JavaScript 對象圖。</param>
 66         /// <param name="behavior">JSON 請求行爲。</param>
 67         public static JsonNetResult JsonNet(this Controller controller, object data, JsonRequestBehavior behavior)
 68         {
 69             return JsonNet(data, (string) null, (Encoding) null, behavior);
 70         }
 71 
 72         /// <summary>
 73         /// 建立 <see cref="T:System.Web.Mvc.JsonNetResult"/> 對象,該對象使用指定內容類型和 JSON 請求行爲將指定對象序列化爲 JavaScript 對象表示法 (JSON) 格式。
 74         /// </summary>
 75         /// 
 76         /// <returns>
 77         /// 將指定對象序列化爲 JSON 格式的結果對象。
 78         /// </returns>
 79         /// <param name="controller">控件器</param>
 80         /// <param name="data">要序列化的 JavaScript 對象圖。</param>
 81         /// <param name="contentType">內容類型(MIME 類型)。</param>
 82         /// <param name="behavior">JSON 請求行爲</param>
 83         public static JsonNetResult JsonNet(this Controller controller, object data, string contentType,
 84             JsonRequestBehavior behavior)
 85         {
 86             return JsonNet(data, contentType, (Encoding) null, behavior);
 87         }
 88 
 89         /// <summary>
 90         /// 建立 <see cref="T:System.Web.Mvc.JsonNetResult"/> 對象,該對象使用內容類型、內容編碼和 JSON 請求行爲將指定對象序列化爲 JavaScript 對象表示法 (JSON) 格式。
 91         /// </summary>
 92         /// 
 93         /// <returns>
 94         /// 將指定對象序列化爲 JSON 格式的結果對象。
 95         /// </returns>
 96         /// <param name="controller">控件器</param>
 97         /// <param name="data">要序列化的 JavaScript 對象圖。</param>
 98         /// <param name="contentType">內容類型(MIME 類型)。</param>
 99         /// <param name="contentEncoding">內容編碼。</param><param name="behavior">JSON 請求行爲</param>
100         public static JsonNetResult JsonNet(this Controller controller, object data, string contentType,
101             Encoding contentEncoding, JsonRequestBehavior behavior)
102         {
103             return JsonNet(data, contentType, contentEncoding, behavior);
104         }
105 
106         /// <summary>
107         /// 建立 <see cref="T:System.Web.Mvc.JsonNetResult"/> 對象,該對象使用內容類型、內容編碼和 JSON 請求行爲將指定對象序列化爲 JavaScript 對象表示法 (JSON) 格式。
108         /// </summary>
109         /// <param name="data">要序列化的 JavaScript 對象圖。</param>
110         /// <param name="contentType">內容類型(MIME 類型)。</param>
111         /// <param name="contentEncoding">內容編碼。</param>
112         /// <param name="behavior"></param>
113         /// <returns>JSON 請求行爲</returns>
114         private static JsonNetResult JsonNet(object data, string contentType, Encoding contentEncoding,
115             JsonRequestBehavior behavior)
116         {
117             return new JsonNetResult()
118             {
119                 Data = data,
120                 ContentType = contentType,
121                 ContentEncoding = contentEncoding,
122                 JsonRequestBehavior = behavior
123             };
124         }
125 
126     }
127 }
Controller擴展方法

 

寫個JsonNetResult類,繼承自JsonResult,重寫ExecuteResult()方法,內部使用JsonNet來序列化。

 1 using System.Text;
 2 using Newtonsoft.Json;
 3 
 4 namespace System.Web.Mvc
 5 {
 6     public class JsonNetResult : JsonResult
 7     {
 8         public Encoding ContentEncoding { get; set; }
 9         public string ContentType { get; set; }
10         public object Data { get; set; }
11 
12         public JsonSerializerSettings SerializerSettings { get; set; }
13         public Formatting Formatting { get; set; }
14 
15         public JsonNetResult()
16         {
17             SerializerSettings = new JsonSerializerSettings();
18         }
19 
20         public override void ExecuteResult(ControllerContext context)
21         {
22             if (context == null)
23                 throw new ArgumentNullException("context");
24 
25             HttpResponseBase response = context.HttpContext.Response;
26 
27             response.ContentType = !string.IsNullOrEmpty(ContentType)
28               ? ContentType
29               : "application/json";
30 
31             if (ContentEncoding != null)
32                 response.ContentEncoding = ContentEncoding;
33 
34             if (Data != null)
35             {
36                 var writer = new JsonTextWriter(response.Output) { Formatting = Formatting };
37 
38                 JsonSerializer serializer = JsonSerializer.Create(SerializerSettings);
39                 serializer.Serialize(writer, Data);
40 
41                 writer.Flush();
42             }
43         }
44     }
45 }
JsonNetResult

 

封裝後的JsonNet序列化

 1 /// <summary>
 2 /// 加載組件列表
 3 /// </summary>
 4 /// <param name="departmentId">做業部/廠</param>
 5 /// <param name="unitId">組件Id</param>
 6 /// <param name="tag">標籤號</param>
 7 /// <param name="pageIndex">當前頁碼</param>
 8 /// <param name="pageSize">每頁條數</param>
 9 /// <returns>返回組件json數據</returns>
10 public JsonNetResult ListCom(long departmentId, IEnumberable<long> unitIds, string tag, int pageIndex, int pageSize)
11 {
12     var dataEntity = LdarService.ListCom(listUnitId, tag, pageIndex + 1, pageSize);
13     var dataModel = new Page<LdComModel> {Total = dataEntity.Total};
14     var data =
15         dataModel.DataList =
16             dataEntity.DataList.Select(model => Builder.Builder.Convert<LdComModel>(new object[] {model}));//Entity轉ViewModel
17     dataModel.DataList = data;
18     return this.JsonNet(new
19     {
20         msg = CommonModelBuilder.BuildQuerySuccessMessage("組件信息維護", (int) dataModel.Total),
21         data = dataModel.DataList,
22         total = dataModel.Total
23     });
24 }

 這樣調用起來跟自帶的Json(...)同樣,很是方便。

因爲時間關係,博客就先寫到這裏。不足及錯誤之處,敬請批評指正。

相關文章
相關標籤/搜索