首页 > 代码库 > 超高性能的json序列化之MVC中使用Json.Net

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

先不废话,直接上代码

Asp.net MVC自带Json序列化

 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 =http://www.mamicode.com/15         dataModel.DataList =16             dataEntity.DataList.Select(model => Builder.Builder.Convert<LdComModel>(new object[] {model}));17     dataModel.DataList = data;18     return Json(new {19             msg = CommonModelBuilder.BuildQuerySuccessMessage("组件信息维护", (int) dataModel.Total),20             data =http://www.mamicode.com/ dataModel.DataList,21             total = dataModel.Total22         });23 }
显示到前台界面

技术分享

请求的报文

技术分享

LdComModel类中关联了很多外表,也就是导航属性,导航也被序列化,这样不科学,会将所有属性包括导航属性都序列化,还可能会造成循环引用,导致报错。
我只想序列需要的字段,这时可以手写一个匿名类
1 var data=http://www.mamicode.com/new {2      model.AreaName,3      model.AreaId,4      ......                  5 };

这么写字段少还好,字段多就很不爽吧。

这时我们可以用Json.Net序列化,首先引用newtonsoft.json.dll,使用nuget引用比较方便。在不想序列化的属性上打上[JsonIgnore]特性,序列化就会被忽略。

 1 /// <summary> 2 /// 分区 3 /// </summary> 4 [JsonIgnore] 5 public LdAreaModel LdAreaModel { get; set; } 6  7 /// <summary> 8 /// 区域名称 9 /// </summary>10 public string AreaName11 {12     get13     {14         return LdAreaModel.LdarAreaName;15     }16 }

 

使用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 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 =http://www.mamicode.com/15         dataModel.DataList =16             dataEntity.DataList.Select(model => Builder.Builder.Convert<LdComModel>(new object[] {model}));17     dataModel.DataList = data;18     var result = new JsonNetResult()19         {20             Data = http://www.mamicode.com/new21             {22                 msg = CommonModelBuilder.BuildQuerySuccessMessage("组件信息维护", (int) dataModel.Total),23                 data =http://www.mamicode.com/ dataModel.DataList,24                 total = dataModel.Total25             }26         };27         return result;28 }

技术分享

导航属性没有被序列化,速度也快了很多。

这样写,虽然可以实现功能,很每次都要new一个JsonNetResult对象,写起来很是不爽,能不能给Controller写个扩展方法,像Json(...)一样直接写JsonNet(...)?

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

 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 =http://www.mamicode.com/ data,27         ContentType = contentType,28         ContentEncoding = contentEncoding,29         JsonRequestBehavior = behavior30       };31     }

我们可以仿照Controller中的源码,自己给Controller写个扩展方法JsonNet(...)

技术分享
  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 = http://www.mamicode.com/data,>

 

写个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               ? ContentType29               : "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 }

 

封装后的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 =http://www.mamicode.com/15         dataModel.DataList =16             dataEntity.DataList.Select(model => Builder.Builder.Convert<LdComModel>(new object[] {model}));17     dataModel.DataList = data;18     return this.JsonNet(new19     {20         msg = CommonModelBuilder.BuildQuerySuccessMessage("组件信息维护", (int) dataModel.Total),21         data =http://www.mamicode.com/ dataModel.DataList,22         total = dataModel.Total23     });24 }

 这样调用起来跟自带的Json(...)一样,非常方便。

由于时间关系,博客就先写到这里。不足及错误之处,敬请批评指正。

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