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

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

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. Oracle在Java中事物管理

    对于 对数据库中的数据做dml操作时,能够回滚,这一事物是很重要的 下面例子是对数据库中数据进行修改 package com.demo.oracle; import java.sql.Connecti ...

  2. Css的使用细谈

    Css的使用细谈 Css可以通过简单的更改CSS文件,改变网页的整体表现形式,可以减少我们的工作量,所以她是每一个网页设计人员的必修课. Css简介              (1) CSS是用于布局 ...

  3. CodeForces768B:Code For 1 (分治)

    Jon fought bravely to rescue the wildlings who were attacked by the white-walkers at Hardhome. On hi ...

  4. POJ 2970 The lazy programmer(贪心+单调优先队列)

    A new web-design studio, called SMART (Simply Masters of ART), employs two people. The first one is ...

  5. OpenResty创造者

    OpenResty 是一个开源的 Web 平台,用于开发高性能和高动态的 Web 网关或者 Web 应用.OpenResty 最早是为了支持全网搜索引擎周边的相关搜索的 API 接口,后来我们基于 N ...

  6. UTC与本地时间字符串互相转换

    #!/usr/bin/env python import time import datetime # 格式自改 UTC_FORMAT = '%Y-%m-%dT%H:%M:%SZ' LOCAL_FOR ...

  7. 发送邮件小工具(python)

    #!/usr/bin/python # -*- coding:UTF- -*- import sys import smtplib import email.mime.multipart import ...

  8. 多叉树结构:JSON数据解析(二)

    多叉树结构:JSON数据解析(二) 在上篇文章中提到了JSON数据解析的基本方法,但是方法效率太低,这里接着上篇文章写写如何利用多叉树结构,定义对象,实现JSON数据字段快速随机访问. JSON数据通 ...

  9. Flutter实战视频-移动电商-31.列表页_列表切换交互制作

    31.列表页_列表切换交互制作 博客地址:https://jspang.com/post/FlutterShop.html#toc-c42 点击左侧的大类右边的小类也跟着变化 新建provide 要改 ...

  10. svn图标更新缓慢

    TSVNCache.exe:在进程管理里有一个Tsvncache.exe这个进程会不定时的对svn目录和非svn目录进行扫描,会造成一定的资源消耗. 此页面允许你选择TSVN为哪些条目显示图标覆盖.选 ...