Fastjson2 序列化过滤器

什么是序列化过滤器?

在日常的 Java 开发中,我们经常需要将对象转换成 JSON 字符串(序列化),或者从 JSON 字符串还原成对象(反序列化)。Fastjson2 是阿里巴巴开源的高性能 JSON 库,它提供了一个非常实用的功能——序列化过滤器,允许我们在序列化过程中动态控制哪些字段需要输出、如何输出。

序列化过滤器,简单来说就是个中间环节:对象要转成JSON的时候,它会决定哪些字段留下、哪些去掉,或者怎么改个样子再出去。

为什么需要过滤器?

假设你有一个用户对象,包含密码、身份证号等敏感信息。直接序列化整个对象可能导致数据泄露。或者你需要在特定场景下只输出部分字段(比如列表页只需要用户名和头像)。传统做法是创建多个 DTO(数据传输对象),但代码会变得冗余。Fastjson2 的过滤器可以优雅地解决这类问题。

核心 API 介绍

Fastjson2 提供了 Filter 接口及其子接口:

  • PropertyFilter:决定属性是否输出
  • NameFilter:修改属性名
  • ValueFilter:修改属性值
  • BeforeFilter:在序列化某个对象前执行自定义操作
  • AfterFilter:在序列化某个对象后执行自定义操作

最常用的是 PropertyFilterValueFilter

实战例子

1. 创建示例对象

public class User {
    private String username;
    private String password;
    private int age;
    private String idCard;
   private int score;
   private int status;
    
}

2. 使用 PropertyFilter 排除字段

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.filter.PropertyFilter;

public class FilterDemo {
    public static void main(String[] args) {
        User user = new User();
        user.setUsername("小明");
        user.setPassword("123456");
        user.setAge(25);
        user.setIdCard("110101199001011234");

        // 只输出非敏感字段
        PropertyFilter filter = (object, name, value) -> {
            // 排除密码和身份证号
            return !"password".equals(name) && !"idCard".equals(name);
        };

        String json = JSON.toJSONString(user, filter);
        System.out.println(json);
        // 输出:{"age":25,"username":"小明"}
    }
}

3. 使用 ValueFilter 修改值

想要在序列化时对值做处理(比如脱敏),可以使用 ValueFilter

import com.alibaba.fastjson2.filter.ValueFilter;

ValueFilter valueFilter = (object, name, value) -> {
    if ("password".equals(name)) {
        return "******"; // 密码脱敏
    }
    if ("idCard".equals(name)) {
        String str = (String) value;
        return str.substring(0, 6) + "********" + str.substring(14);
    }
    return value; // 其他字段不变
};

String json = JSON.toJSONString(user, valueFilter);
System.out.println(json);
// 输出:{"age":25,"idCard":"110101********1234","password":"******","username":"小明"}

4. 组合使用多个过滤器

Fastjson2 支持同时应用多个过滤器,按照添加顺序执行:

import com.alibaba.fastjson2.filter.Filter;

// 先过滤字段,再脱敏
Filter combinedFilter = FilterUtils.combine(filter, valueFilter);
// 或者直接传数组
String json = JSON.toJSONString(user, new Filter[]{filter, valueFilter});

高级用法:BeforeFilter 动态增加字段

有时需要在序列化时额外添加一些计算出的字段:

import com.alibaba.fastjson2.filter.BeforeFilter;

BeforeFilter beforeFilter = new BeforeFilter() {
    @Override
    public void writeBefore(Object object) {
        User user = (User) object;
        // 动态添加一个字段 "userType": "VIP"
        writeKeyValue("userType", user.getAge() > 18 ? "VIP" : "普通");
    }
};

String json = JSON.toJSONString(user, beforeFilter);
// 输出 {"userType":"VIP","age":25,"idCard":"110101199001011234","password":"123456","username":"小明"}

相应的AfterFilter例子:

import com.alibaba.fastjson2.filter.AfterFilter;

AfterFilter afterFilter = new AfterFilter() {
    @Override
    public void writeAfter(Object object) {
        User user = (User) object;
        // 在序列化完成后动态添加字段
        writeKeyValue("userLevel", user.getScore() > 100 ? "黄金会员" : "普通会员");
        writeKeyValue("isActive", user.getStatus() == 1);
    }
};

String json = JSON.toJSONString(user, afterFilter);
// 输出 {"age":25,"idCard":"110101199001011234","password":"123456","username":"小明","userLevel":"普通会员","isActive":true}

实际应用场景

  1. 接口数据裁剪:不同 API 返回不同字段集,减少网络传输量
  2. 敏感信息脱敏:密码、身份证号、手机号等在日志或非安全环境中脱敏
  3. 字段重命名:将 Java 的驼峰命名转为下划线命名(NameFilter 实现)
  4. 日志过滤:避免打印过大的二进制数据或敏感信息

小结

Fastjson2 的序列化过滤器提供了灵活、优雅的方式来控制 JSON 输出。相比创建多个 DTO 类,过滤器方式代码更简洁,维护更方便。