zoukankan      html  css  js  c++  java
  • 超高性能的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}));//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]特性,序列化就会被忽略。

    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序列化

     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中没有多余的导航属性.

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

    这样写,虽然可以实现功能,很每次都要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(...)

      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(...)一样,非常方便。

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

  • 相关阅读:
    Python利用Remove.bg接口自动消除图片背景
    解决ajxa跨域问题
    CentOS7 修改静态IP
    CentOS下 安装composer 与tp5.1
    centon 安装php-fpm+Nginx
    win10 安装selenium和使用
    Scrapy 爬虫框架入门
    Python 异常处理
    selenium和phantomjs的介绍
    MongoDB入门
  • 原文地址:https://www.cnblogs.com/xiaoafei1991/p/4196223.html
Copyright © 2011-2022 走看看