应无所住,而生其心
排名
1
文章
860
粉丝
112
评论
163
net core webapi post传递参数
庸人 : 确实坑哈,我也是下班好了好几次,发现后台传递对象是可以的,但...
百度编辑器自定义模板
庸人 : 我建议换个编辑器,因为现在百度富文本已经停止维护了,用tinymec...
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

.net webapi Newtonsoft.Json返回需要的字段,忽略某些字段,修改字段名,动态返回需要的字段等

15120人阅读 2019/11/12 14:33 总访问:5179894 评论:3 收藏:1 手机
分类: .NET

有时候我们在写webapi的时候,不想把正常用的对象所有字段都返回,我们需要进行一些筛选,忽略某些字段,大概说一下几种方法


方法一:给不同需求单独写查询,提供不同的数据对象

单独写一个model,然后单独写一个查询,在通过接口提供出去

这种方法效率比较高,不需要单独解析一下,就是代码量多一点,适用于变化不大的情况。

当然也可能是这个接口是需要依赖与另外一个接口返回的数据,道理是一样,就是对数据源加工后进去返回,至于数据源是数据库还是缓存还是其他接口提供的数据不影响我们数据加工几种方法的使用


方法二:使用对象映射

单独写一个model,把原有model赋值到另外的对象,使用automapper或者自己通过反射映射一下对象即可 这样写法要通过反射转化一遍,效率会慢一点,但是可以共用一个查询方法。

想要修改字段名可以自己弄一个映射关系,用特性或者动态映射都可以,automapper映射一个名字还是比较方便的

          

方法三:通过Newtonsoft.Json在model中配置忽略某些值即可

 通过JsonIgnore特性配置即可。

 如下:我们可以忽略AClass与AClassId字段

 

 因为net core中默认就是使用的Newtonsoft.Json序列化json所以这样就可以了,不需要借助其他东西做其他操作

 效果如下:

  没有忽略前

             

  忽略后,会看到字段没有了

             

这种写法不需要借助其他第三方的东西,配置一下即可。但是还是会影响一些效率,json序列化的时候会进行判断,但是效率优于自己写反射解析,而且不需要自己重新写一个model。不过灵活性差一点,如果有两个用户需要返回不同的字段,只有这一种方式就不是很好的实现


想要改变一下名字也是很方便的,直接使用JsonProperty即可

如下我想把SContent换成Summary

用JsonProperty特性指定一下即可:

  1. //文章摘要信息
  2. [JsonProperty(PropertyName = "Summary")]
  3. public string SContent { getset; }

 我们可以看到原有的名字已经被修改成Summary了



方法四:通过生成动态类型ExpandoObject

这种写法可以根据不传递的需要返回的字段,或者传递想要忽略的字段动态构建一个类型,然后返回前台,这种方式很灵活,适用于用户需求变化大的情况,或者说某些特殊的数据返回需求,可以和第三种方法结合使用,一个提供标准化服务一个提供特殊化服务。

这种写法由于会使用到反射和动态构建一个ExpandoObject所以效率会不如直接返回model和第三种配置json忽略的写法,而且返回值还必须是ExpandoObject,如果我们model是一个很多对象组合在一起的会降低一点代码可读性。

具体做法参考博客:http://www.tnblog.net/hb/article/details/2788

他这里没有提供忽略某些字段的写法,我来补充一个:

  1. public class LimitPropsContractResolver : DefaultContractResolver
  2.     {
  3.         string[] props = null;
  4.         public enum LimitType { Contains, Ignore }
  5.         public LimitType limitType;
  6.         /// <summary>
  7.         /// 构造函数
  8.         /// </summary>
  9.         /// <param name="props">传入的属性数组</param>
  10.         /// <param name="retain">true:表示props是需要保留的字段  false:表示props是要排除的字段</param>
  11.         public LimitPropsContractResolver(string[] props, LimitType limitType = LimitType.Contains)
  12.         {
  13.             //指定要序列化属性的清单
  14.             this.props = props;
  15.             this.limitType = limitType;
  16.         }
  17.         protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
  18.         {
  19.             IList<JsonProperty> list = base.CreateProperties(type, memberSerialization);
  20.             //只保留清单有列出的属性
  21.             return list.Where(p =>
  22.             {
  23.                 if (limitType == LimitType.Contains)
  24.                 {
  25.                     //匹配的时候为了不区分大小写
  26.                     return props.FirstOrDefault(a => a.ToLower() == p.PropertyName.ToLower()) != null;
  27.                 }
  28.                 else
  29.                 {
  30.                     return props.FirstOrDefault(a => a.ToLower() == p.PropertyName.ToLower()) == null;
  31.                 }
  32.             }).ToList();
  33.         }
  34.     }

用法,比如要忽略aClass与aClassId字段:

  1. #region 忽略aClass与aClassId字段
  2. var result = art.ToDynamicIgnore("aClass,aClassId");
  3. returnModel.Value.dto_Article = result;
  4. #endregion


补充方法三.1:通过Newtonsoft.Json实现动态需要返回的字段

有些时候我们需要动态的返回字段给不同的用户,比如小明用户需要A,B,C三个字段,小红需要C,M,D。虽然可以使用第四种方法实现,但是我们可以直接通过Newtonsoft.Json来实现,不需要重新写一个model,也不需要动态构建一个ExpandoObject。

通过扩展DefaultContractResolver来实现:

  1. public class LimitPropsContractResolver : DefaultContractResolver
  2.     {
  3.         string[] props = null;
  4.         public enum LimitType { Contains, Ignore }
  5.         public LimitType limitType;
  6.         /// <summary>
  7.         /// 构造函数
  8.         /// </summary>
  9.         /// <param name="props">传入的属性数组</param>
  10.         /// <param name="retain">true:表示props是需要保留的字段  false:表示props是要排除的字段</param>
  11.         public LimitPropsContractResolver(string[] props, LimitType limitType = LimitType.Contains)
  12.         {
  13.             //指定要序列化属性的清单
  14.             this.props = props;
  15.             this.limitType = limitType;
  16.         }
  17.         protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
  18.         {
  19.             IList<JsonProperty> list = base.CreateProperties(type, memberSerialization);
  20.             //只保留清单有列出的属性
  21.             return list.Where(p =>
  22.             {
  23.                 if (limitType == LimitType.Contains)
  24.                 {
  25.                     //匹配的时候为了不区分大小写
  26.                     return props.FirstOrDefault(a => a.ToLower() == p.PropertyName.ToLower()) != null;
  27.                 }
  28.                 else
  29.                 {
  30.                     return props.FirstOrDefault(a => a.ToLower() == p.PropertyName.ToLower()) == null;
  31.                 }
  32.             }).ToList();
  33.         }
  34.     }

比如我们只想取 title和aClass两个字段如下即可

  1. //动态查询想要的字段
  2. JsonSerializerSettings jsetting = new JsonSerializerSettings();
  3. jsetting.ContractResolver = new LimitPropsContractResolver(new string[] { "title""aClass" });
  4. string jsonstr = JsonConvert.SerializeObject(art, Formatting.Indented, jsetting);

效果如下:

如果想要忽略的话,也很简单,通过自己封装的枚举指定一下: LimitType.Ignore

  1. //动态忽略想要的字段
  2. JsonSerializerSettings jsetting = new JsonSerializerSettings();
  3. jsetting.ContractResolver = new LimitPropsContractResolver(new string[] { "id""title""aClass" }, LimitType.Ignore);
  4. string jsonstr = JsonConvert.SerializeObject(art, Formatting.Indented, jsetting);


补充方法三.2:通过Newtonsoft.Json实现动态修改名字

有时候我们想要给不同的用户或者客户端提供不同的名字,又比如不同前台的组件需要不同格式的数据,我们可以动态的修改名字就不用为每个都重新定义一个新的模型。

和修改返回字段一样的去重写DefaultContractResolver

  1. public class PropsContractResolver : DefaultContractResolver
  2. {
  3.     Dictionary<stringstring> dict_props = null;
  4.     /// <summary>
  5.     /// 构造函数
  6.     /// </summary>
  7.     /// <param name="props">传入的属性数组</param>
  8.     public PropsContractResolver(Dictionary<stringstring> dictPropertyName)
  9.     {
  10.         //指定字段要序列化成什么名称
  11.         this.dict_props = dictPropertyName;
  12.     }
  13.     protected override string ResolvePropertyName(string propertyName)
  14.     {
  15.         string newPropertyName = string.Empty;
  16.         if (dict_props != null && dict_props.TryGetValue(propertyName, out newPropertyName))
  17.         {
  18.             return newPropertyName;
  19.         }
  20.         else
  21.         {
  22.             //没有找到就用原来的
  23.             return base.ResolvePropertyName(propertyName);
  24.         }
  25.     }
  26. }

使用:

  1. JsonSerializerSettings jsetting = new JsonSerializerSettings();
  2. //jsetting.ContractResolver = new LimitPropsContractResolver(new string[] { "title", "aClass" }, LimitType.Contains);
  3. Dictionary<stringstring> dictProp = new Dictionary<stringstring> { { "Id""MyId" }, { "Title""MyTitle" } };
  4. jsetting.ContractResolver = new PropsContractResolver(dictProp);
  5. string jsonstr = JsonConvert.SerializeObject(art, Formatting.Indented, jsetting);

这里我们把Id修改成了MyId,Title修改成了MyTitle


补充方法三.3:可以把筛选字段和修改字段名字的统一起来

因为貌似json的配置只能指定一个,所以把两个方法组合起来一起用,可以同时作用

  1. public class LimitPropsContractResolver : DefaultContractResolver
  2. {
  3.     string[] props = null;
  4.     public enum LimitType { Contains, Ignore }
  5.     public LimitType limitType;
  6.     Dictionary<stringstring> dict_props = null;
  7.     /// <summary>
  8.     /// 构造函数
  9.     /// </summary>
  10.     /// <param name="props">传入的属性数组</param>
  11.     /// <param name="retain">true:表示props是需要保留的字段  false:表示props是要排除的字段</param>
  12.     public LimitPropsContractResolver(string[] props, LimitType limitType = LimitType.Contains, Dictionary<stringstring> dictPropertyName=null)
  13.     {
  14.         //指定要序列化属性的清单
  15.         this.props = props;
  16.         this.limitType = limitType;
  17.         this.dict_props = dictPropertyName;
  18.     }
  19.     protected override string ResolvePropertyName(string propertyName)
  20.     {
  21.         string newPropertyName = string.Empty;
  22.         if (dict_props != null && dict_props.TryGetValue(propertyName, out newPropertyName))
  23.         {
  24.             return newPropertyName;
  25.         }
  26.         else
  27.         {
  28.             //没有找到就用原来的
  29.             return base.ResolvePropertyName(propertyName);
  30.         }
  31.     }
  32.     protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
  33.     {
  34.         IList<JsonProperty> list = base.CreateProperties(type, memberSerialization);
  35.         //只保留清单有列出的属性
  36.         return list.Where(p =>
  37.         {
  38.             if (limitType == LimitType.Contains)
  39.             {
  40.                 //匹配的时候为了不区分大小写
  41.                 return props.FirstOrDefault(a => a.ToLower() == p.PropertyName.ToLower()) != null;
  42.             }
  43.             else
  44.             {
  45.                 return props.FirstOrDefault(a => a.ToLower() == p.PropertyName.ToLower()) == null;
  46.             }
  47.         }).ToList();
  48.     }
  49. }

使用的时候要注意,因为两个组合起来使用了,取需要字段的时候应该是给修改名字之后的,这样就可以的

但是如果这样写就不行:


补充方法三.4:筛选字段和修改字段名字的同时可以实现json命名的配置

如下想要实现自带的驼峰法命名,直接把我们自定义的继承驼峰法命名那个即可

当然如果你想要让他支持多命名的也可以做成配置的方式



webapi运用自定义json格式请参考:

http://www.tnblog.net/aojiancc2/article/details/2831



tip:以上几种方法可以根本不同的业务场景选择一种或者几种方法使用





欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739。有需要软件开发,或者学习软件技术的朋友可以和我联系~(Q:815170684)

评价

雨雨雨雨辰

2019/11/12 15:35:15

疯狂反射


剑轩:@雨雨雨雨辰没有反射代码世界会少了灵魂[手动斜眼笑]

2019/11/12 16:07:21 回复

雨雨雨雨辰

2019/11/12 16:37:19

已精

css弹性盒子flex布局

css弹性盒子由于版本不同浏览器问题造成了一些不同的写法display:flexbox;在google浏览器中如果使用下面的写法就不行displa...

可输入下拉文本框据输入动态加载数据 jquery-editable-select

用到一个jquery-editable-select的控件github地址:https://github.com/indrimuska/jquery-editable-select这个插件的原理是...

.net mvc分部页.net core分部页

.net分部页的三种方式第一种:@Html.Partial(&quot;_分部页&quot;)第二种:@{ Html.RenderPartial(&quot;分部页&quot;);}...

css中单位pxemrem和vh/vw的理解

&gt;px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的。em是相对长度单位。相对于当前对象内文本的字...

让IIS支持webp格式图片让IIS支持vtt格式iis设置mime类型iis配置支持的类型

webp格式图片可以让图片体积变小。也让下载图片变得更加困难一点 在线制作webp工具 https://www.upyun.com/webp?utm_mediu...

网页上传文件断点续传的实现无视文件大小上传以及datatables基本用法

首先明白js是客户带执行代码,c#是服务器上执行代码。本地文件需要用到js处理,服务器端接受c#代码处理1.HTML页面,文件信...

如何使用图标像使用文字一样使用文本图标的方法

1.首先在Iconfont-阿里巴巴矢量图标库上面找到你需要的图标然后加入你的购物车然后选择图标;注意:每个类型的图标会大小不...

使用七牛云的cdn服务提高图片的加载速度

CDN介绍CDN的全称是Content Delivery Network,即内容分发网络。CDN加速主要是加速静态资源,如网站上面上传的图片、媒体,...

通俗易懂什么是.net?什么是.net Framework?什么是.net core?

朋友圈@蓝羽 看到一篇文章写的太详细太通俗了,搬过来细细看完,保证你对.NET有个新的认识理解原文地址:https://www.cnblo...

JS监听input、keydown有输入法时打字完成后触发事件

在给输入框绑定input或keydown事件时预期效果是有输入法时,输入中文后触发事件,不希望输一个字母就触发一次事件可以用到c...

修改了css后让浏览器从缓存中更新

当我们修改了css后,如果不做一些操作,浏览器是不会自动更新我们的样式文件的。除非是过期或者用户手动刷新清理缓存等。所...

C MVC RedirectToAction跳转时候传递参数Action之间传值

MVC Action之间传值,页面跳转传值方法一:路由传值很简单直接使用 RedirectToAction(string actionName, string controller...

当你工作遇到以下几种状态时请果断跳槽走人

已经有想跳槽的念头,但是一直磨磨蹭蹭、犹犹豫豫的混日子,这种念头或者一直持续,或者是不是冒出头来占据你的思维了。于...

C与Java二进制编码转换补码

在C#与Java接口对接时,需要将图片转化为二进制编码传输,这时候发现c#转换出来的编码的值是0~255的范围,而java方需要的是...