You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jackson自定义过滤器未触发,如何实现指定字段过滤需求?

问题描述

原始JSON对象:

{"username":"johndoe","email":"john.doe@example.com",
"secretToken":"token123","secretKey":"password","phoneNumber":"518-555-1234","active":true}

需要实现两个过滤规则:

  • 移除所有以secret开头的字段
  • 移除所有值为true的布尔类型字段

期望输出:

{"username":"johndoe","email":"john.doe@example.com",
"phoneNumber":"518-555-1234"}

已编写自定义CustomStaticBeanPropertyFilter过滤器,在User实体类上标注@JsonFilter,并在main方法中配置Jackson,但自定义过滤器未触发。尝试过serializeAllExcept方法可行但不符合需求,更换过滤器调用方式也无效。当前使用Jackson 2.15.2 + Java 8,版本可调整。

问题原因
  1. 重复的@JsonFilter注解:在User类的isActive()方法上额外添加了@JsonFilter("customFilter"),导致Jackson无法正确识别类级别的过滤器配置,进而使自定义过滤器无法触发。
  2. 过滤器逻辑注释错误:代码中注释写的是"Exclude fields with false values",但实际逻辑是排除值为true的布尔字段,虽然逻辑正确,但注释容易误导后续维护。
修正后的代码

自定义过滤器

public static class CustomStaticBeanPropertyFilter extends SimpleBeanPropertyFilter {

    @Override
    public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, BeanPropertyWriter writer)
        throws Exception {
      String fieldName = writer.getName();
      Object fieldValue = writer.get(pojo);

      // 排除以"secret"开头的字段
      if (fieldName.startsWith("secret")) {
        return;
      }

      // 排除null值字段
      if (fieldValue == null) {
        return;
      }

      // 排除值为true的布尔类型字段
      if (fieldValue instanceof Boolean && (Boolean) fieldValue) {
        return;
      }

      // 序列化其他符合要求的字段
      writer.serializeAsField(pojo, jgen, provider);
    }

    @Override
    protected boolean include(BeanPropertyWriter writer) {
      return true; // 默认包含所有字段,由serializeAsField逻辑决定是否过滤
    }

    @Override
    protected boolean include(PropertyWriter writer) {
      return true; // 默认包含所有字段,由serializeAsField逻辑决定是否过滤
    }
}

User实体类

@JsonFilter("customFilter")
public static class User {
    private String username;
    private String email;
    private String secretToken;
    private String secretKey;
    private String phoneNumber;
    private boolean isActive;

    public User() {}

    public User(String username, String email, String secretToken, String secretKey, String phoneNumber, boolean isActive) {
      this.username = username;
      this.email = email;
      this.secretToken = secretToken;
      this.secretKey = secretKey;
      this.phoneNumber = phoneNumber;
      this.setActive(isActive);
    }

    // Getters and Setters
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }

    public String getSecretToken() { return secretToken; }
    public void setSecretToken(String secretToken) { this.secretToken = secretToken; }

    public String getSecretKey() { return secretKey; }
    public void setSecretKey(String secretKey) { this.secretKey = secretKey; }

    public String getPhoneNumber() { return phoneNumber; }
    public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; }

    // 移除此处的@JsonFilter注解
    public boolean isActive() { return isActive; }
    public void setActive(boolean isActive) { this.isActive = isActive; }
}

调用代码

public static void main(String[] args) throws IOException {
    User user = new User("johndoe", "john.doe@example.com", "token123", "password", "518-555-1234", true);

    ObjectMapper mapper = new ObjectMapper();

    SimpleFilterProvider filterProvider = new SimpleFilterProvider()
        .addFilter("customFilter", new CustomStaticBeanPropertyFilter());

    mapper.setFilterProvider(filterProvider);
    String serializedUser = mapper.writeValueAsString(user);

    System.out.println(serializedUser);
}

内容的提问来源于stack exchange,提问作者jgp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 14:37:13