zoukankan      html  css  js  c++  java
  • Jackson 动态过滤属性,编程式过滤对象中的属性

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

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

    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

  • 相关阅读:
    【下载源码】在线生成网页缩略图.超越Snap.com:WebSnap Beta 1.1 发布。感谢博客园的“萧寒”重写的底层。开源。
    有时候看.neter的表现,真的很奇怪。那种近在眼前而不见的茫然,真的让你为之着急——说说XML的无效字符
    初来乍到,发布一个杀手应用:snap.com的web预览图功能,我给它取名叫“WebSnap”
    湖南长沙火车站,我为你感到羞愧。
    也谈UpdatePanel与UrlRewrite一起work时出现Form Action属性的问题
    JAVA的内存管理
    Handler+looper+Message的分享教程。 转
    更改TabHost标签的背景
    多线程任务的优化1:探讨AsyncTask的缺陷【转】
    聊天类android应用的一些技术细节
  • 原文地址:https://www.cnblogs.com/huzi007/p/6626990.html
Copyright © 2011-2022 走看看