Fork me on GitHub
超高性能的json序列化

超高性能的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(...)一样,非常方便。

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

 
 
标签: MVCJSON
posted on 2015-01-23 09:27  HackerVirus  阅读(492)  评论(0编辑  收藏  举报