超高性能的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 = 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 = 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]特性,序列化就会被忽略。
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序列化
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})); 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 }
导航属性没有被序列化,速度也快了很多。
这样写,虽然可以实现功能,很每次都要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 = data, 27 ContentType = contentType, 28 ContentEncoding = contentEncoding, 29 JsonRequestBehavior = behavior 30 }; 31 }
我们可以仿照Controller中的源码,自己给Controller写个扩展方法JsonNet(...)
Controller扩展方法
写个JsonNetResult类,继承自JsonResult,重写ExecuteResult()方法,内部使用JsonNet来序列化。
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})); 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(...)一样,非常方便。
由于时间关系,博客就先写到这里。不足及错误之处,敬请批评指正。