场景:有时候我们做系统的时候,比如两个请求,返回同一个对象,但是需要的返回字段并不相同。

常见与写前端接口的时候,尤其是手机端,一般需要什么数据就返回什么样的数据。此时对于返回同一个对象我们就要动态过滤所需要的字段...

Spring MVC 默认使用转json框架是 jackson。 大家也知道, jackson 可以在实体类内加注解,来指定序列化规则,但是那样比较不灵活,不能实现我们目前想要达到的这种情况

下面用编程式的方式实现过滤字段.

先写个json工具类:

public class JsonUtilJackson {

    private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static final ObjectMapper mapper; JacksonJsonFilter jacksonFilter = new JacksonJsonFilter(); static {
SimpleDateFormat dateFormat = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
mapper = new ObjectMapper();
mapper.setDateFormat(dateFormat);
// 允许对象忽略json中不存在的属性
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 允许出现特殊字符和转义符
mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
// 允许出现单引号
mapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);
// 忽视为空的属性
mapper.setSerializationInclusion(Include.NON_EMPTY);
} public static JsonUtilJackson me() {
JsonUtilJackson jsonUtil = new JsonUtilJackson();
return jsonUtil;
} public void filter(Class<?> clazz, String include, String filter) {
if (clazz == null)
return;
if (StringUtils.isNotBlank(include)) {
jacksonFilter.include(clazz, include.split(","));
}
if (StringUtils.isNotBlank(filter)) {
jacksonFilter.filter(clazz, filter.split(","));
}
mapper.addMixIn(clazz, jacksonFilter.getClass());
} public String toJson(Object obj) {
try {
mapper.setFilterProvider(jacksonFilter);
return mapper.writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException("转换json字符失败!");
}
} public <T> T toObject(String json, Class<T> clazz) {
try {
return mapper.readValue(json, clazz);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("将json字符转换为对象时失败!");
}
} public <T> T toObject(String json, TypeReference<T> clazz) {
try {
return mapper.readValue(json, clazz);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("将json字符转换为对象时失败!"); }
} }

然后写个JsonFilter

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set; import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.BeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.PropertyFilter;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; @SuppressWarnings("deprecation")
@JsonFilter("JacksonFilter")
public class JacksonJsonFilter extends FilterProvider{ Map<Class<?>, Set<String>> includeMap = new HashMap<>();
Map<Class<?>, Set<String>> filterMap = new HashMap<>(); public void include(Class<?> type, String[] fields) {
addToMap(includeMap, type, fields);
} public void filter(Class<?> type, String[] fields) {
addToMap(filterMap, type, fields);
} private void addToMap(Map<Class<?>, Set<String>> map, Class<?> type, String[] fields) {
Set<String> filedSet=new HashSet<>();
if(fields!=null && fields.length>0){
for(String filed : fields){
filedSet.add(filed);
}
}
map.put(type, filedSet);
} @Override
public BeanPropertyFilter findFilter(Object filterId) {
throw new UnsupportedOperationException("Access to deprecated filters not supported");
} @Override
public PropertyFilter findPropertyFilter(Object filterId, Object valueToFilter) { return new SimpleBeanPropertyFilter() { @Override
public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer)
throws Exception {
if (apply(pojo.getClass(), writer.getName())) {
writer.serializeAsField(pojo, jgen, prov);
} else if (!jgen.canOmitFields()) {
writer.serializeAsOmittedField(pojo, jgen, prov);
}
}
};
} public boolean apply(Class<?> type, String name) {
Set<String> includeFields = includeMap.get(type);
Set<String> filterFields = filterMap.get(type);
if (includeFields != null && includeFields.contains(name)) {
return true;
} else if (filterFields != null && !filterFields.contains(name)) {
return true;
} else if (includeFields == null && filterFields == null) {
return true;
}
return false;
} }

最后就是我们测试了

    public static void main(String[] args) throws Exception {

        A a=new A();
a.setName("AAAAA");
a.setNo("011111"); Role r=new Role();
r.setName("zhangsan");
r.setCode("11");
r.setCreateTime(new Date().getTime());
r.setRemark("who am i"); a.setR(r); JsonUtilJackson jtk= new JsonUtilJackson();
// 设置转换 Article 类时,只包含 id, name
jtk.filter(A.class, "no,r", null);
jtk.filter(Role.class, "name,remark", null);
String ss=jtk.toJson(a);
System.out.println(ss); }

结果:{"no":"011111","r":{"name":"zhangsan","remark":"who am i"}}

参考:https://my.oschina.net/diamondfsd/blog/836727?p=3&temp=1490578919756#blog-comments-list

Jackson 动态过滤属性,编程式过滤对象中的属性的更多相关文章

  1. spring data mongodb中,如果对象中的属性不想加入到数据库字段中

    spring data mongodb中,如果对象中的属性不想加入到数据库字段中,可加@Transient注解,声明为透明属性 spring data mongodb 官网帮助文档 http://ww ...

  2. JavaScript 深入了解对象中的属性

    本篇主要介绍JS中对象的属性,包括:属性的分类.访问方式.检测属性.遍历属性以及属性特性等内容. 目录 1. 介绍:描述属性的命名方式.查找路径以及分类 2. 属性的访问方式:介绍'.'访问方式.'[ ...

  3. java工具类之按对象中某属性排序

    import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang ...

  4. 在Map对象中获取属性,注意判断为空

    在Map对象中获取属性,注意判断为空 public static void main(String[] args) { Map map = new HashMap(); Integer i = (In ...

  5. 遍历js对象中的属性

    可以使用js自带的for in.也可以使用Ext JS中的方法来遍历js对象中的属性 代码如下: /** 遍历对象 */ var person = {name:'张泰松',age:28}; //js方 ...

  6. JS基础_枚举对象中的属性

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. 枚举对象中的属性 for . . in

    枚举对象中的属性:把对象中所有的属性和值都取出来 使用 for . . . in 语句 语法: for(var  变量  in  对象){ } for  . . . in 语句  对象中有几个属性,循 ...

  8. 微信小程序:给data中对象中的属性设置值与给data中的属性或对象或数组设置值的区别

    一.给data中的属性或对象或数组设置值,属性名不需要加引号 this.setData({ material: param, // 这里material为对象 } this.setData({   d ...

  9. C#验证对象中的属性是否为空的共通方法

    在后台接口处理时,经常需要对请求的参数做验证.因此提取了共通方法,方便进行判断. /// <summary> /// 数据验证工具类 /// </summary> public ...

随机推荐

  1. 004-画图神器-graphviz

    1 安装及基本使用 1) 下载安装 下载地址 可以下载安装版进行安装或者解压版直接使用 2) 添加系统path 为了能够在dos中使用命令, 需要添加环境变量 默认安装路径为 C:\Program F ...

  2. 【CQ18高一暑假前挑战赛2】标程

    [昨晚打校赛,5个小时打完很累了,所以搞忘出题了...对不起学弟们,不过出的题都亲自写过一遍,可以保证题目和代码长度都不长,题目难度不大] [A:bush博弈] #include<bits/st ...

  3. Python 黑帽子第二章运行截图

  4. Ubuntu+win7 双系统修改开机启动项顺序

    Ubuntu和windows双系统安装完后默认Ubuntu系统是第一启动项,等待时间是10秒 如果你想改成windows为第一启动项 先进去Ubuntu系统 打开终端 (Ctrl+Alt+T) 修改启 ...

  5. vue-router 安装

    如果在一个模块化工程中使用它,需要通过Vue.use() 明确的安装路由功能,如果使用全局的script标签,则不需要手动安装. Vue Router是Vue.js官方的路由管理器.它和Vue.js的 ...

  6. error:对‘vtable for new_sequence’未定义的引用 对‘typeinfo for num_sequence’未定义的引用

    在设计父类子类继承关系中,经常会出现此类问题. 报错原因:父类中的虚函数只有声明,没有定义. 解决方案 : 1. 定义相关的虚函数的实现. 2. 不实现了,直接搞成纯虚函数留给后代实现. virtua ...

  7. 技术胖Flutter第三季-15垂直布局Column组件

    博客地址: https://jspang.com/post/flutter3.html#toc-8eb 垂直布局 左对齐: crossAxisAlignment: CrossAxisAlignment ...

  8. Flutter实战视频-移动电商-65.会员中心_订单区域UI布局

    65.会员中心_订单区域UI布局 我的订单区域 member.dart写我的标题的方法 布局使用瓦片布局 先做修饰,decoration颜色的背景,下边线的样式 //我的订单标题 Widget _or ...

  9. Identity Server 4 原理和实战(完结)_Resource Owner Password Credentials 授权实例

    今天要讲的 用fiddler来监听,昨天的客户端的请求 这是一个post的请求 这是响应的数据 Expores_in超时时间, 今天的内容 在服务端再声明一个client端 wpf的应用的效果图 首先 ...

  10. CodeForces 496D Tennis Game (暴力枚举)

    题意:进行若干场比赛,每次比赛两人对决,赢的人得到1分,输的人不得分,先得到t分的人获胜,开始下场比赛,某个人率先赢下s场比赛时, 游戏结束.现在给出n次对决的记录,问可能的s和t有多少种,并按s递增 ...