Jackson 动态过滤属性,编程式过滤对象中的属性

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

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/108594.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • SplitContainer容器控件左右Panel大小调整「建议收藏」

    SplitContainer容器控件左右Panel大小调整「建议收藏」1、新建一个Winform窗体,从上图中选择SplitContainer空间,拖拽到Form到上,如下图:2、你会发现,随便点击Panel1或者Panel2,会显示出粗框,但怎么调整两个Panel的大小呢?两个Panel之间的那条线,是选不中的,哈哈,不信可以试试。那么如何才能调整两个Form的大小呢?==》随便单击一个Panel,再按一下Esc,会出现下图:这时,

    2022年7月18日
    93
  • 将十进制转化为二进制的c语言程序_十进制111转换二进制

    将十进制转化为二进制的c语言程序_十进制111转换二进制目录十进制与二进制之间的转换十进制转换二进制C++实现十进制转换二进制二进制转换十进制C++实现二进制转换十进制十进制与二进制之间的转换十进制转换二进制十进制对2整除,得到的余数的倒序即为转换而成的二进制十进制转换二进制C++实现十进制转换二进制主函数main.cpp为:#include<iostream>#include<…

    2022年10月10日
    0
  • 摘星-上升篇

    以下内容均来自阳光占星,如有冒犯,告知删除!上升金牛——歌者的哼唱有这么一类人,可能有着细致柔和的五官,容易发胖的体质以及坚定的眼神。有点害羞与腼腆;喜欢哼唱着小曲,不喜欢拥挤的人群而喜欢宁静的自然。这样的一群人就是生活在我们身边的上升金牛。他们喜欢舒缓的生活节奏,喜欢按照自己的节奏去一点点的完成计划,不喜欢突如其来的变动扰乱了自己的生活。金牛是一个喜欢稳定和安逸的星座,并且由于金牛的守护星为金星,上升金牛也诞生出更多的艺术色彩。但上升金牛的审美一直被吐槽,旁人就必须忍受他那万年…

    2022年4月6日
    72
  • JAVA设计模式之享元模式

    解释一下概念:也就是说在一个系统中如果有多个相同的对象,那么只共享一份就可以了,不必每个都去实例化一个对象。比如说一个文本系统,每个字母定一个对象,那么大小写字母一共就是52个,那么就要定义52个对象。如果有一个1M的文本,那么字母是何其的多,如果每个字母都定义一个对象那么内存早就爆了。那么如果要是每个字母都共享一个对象,那么就大大节约了资源。  在Flyweight模式中,由于要产生各种各样

    2022年3月11日
    46
  • YUV格式到底是什么?

    YUV格式到底是什么?简介YUV是视频、图片、相机等应用中使用的一类图像格式,实际上是所有“YUV”像素格式共有的颜色空间的名称。与RGB格式(红-绿-蓝)不同,YUV是用一个称为Y(相当于灰度)的“亮度”分量和两个“色度”分量表示,分别称为U(蓝色投影)和V(红色投影),由此得名。YUV也可以称为YCbCr,虽然这些术语意味着略有不同,但它们往往会混淆并可互换使用。Y表示亮度分量:如果只显示Y的话,…

    2022年7月16日
    22
  • Mysql之锁、事务绝版详解—干货!

    Mysql之锁、事务绝版详解—干货!

    2022年2月10日
    34

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号