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

基于Jackson实现JSON序列化时按需移除敏感属性的方案咨询

解决Jackson序列化时动态过滤敏感属性的方案

这确实是个很常见的序列化场景需求——同一个类对象既要在安全环境下完整序列化,又要在存数据库时自动移除敏感属性,同时还不能直接把这些属性标记为永久忽略。Jackson提供了几种精准的方案来处理,咱们一个个说:

1. 你考虑的Jackson Views:场景化固定过滤

Jackson Views完全能满足你的基础需求,而且实现起来很直观。核心思路是给不同的序列化场景定义标记类,然后给敏感属性打上对应场景的排除标记:

  • 首先定义两个View标记类:
public class Views {
    // 安全环境下的完整序列化视图
    public static class Full {}
    // 存数据库时的脱敏视图
    public static class DatabaseSafe {}
}
  • 然后在你的实体类中给敏感属性标记@JsonView:
public class YourEntity {
    // 普通属性,所有视图都序列化
    private String normalProperty;

    // 敏感属性,只在Full视图下序列化
    @JsonView(Views.Full.class)
    private String sensitiveProperty1;

    @JsonView(Views.Full.class)
    private String sensitiveProperty2;
}
  • 序列化时指定对应的视图即可:
// 安全环境下完整序列化
ObjectMapper fullMapper = new ObjectMapper();
String fullJson = fullMapper.writerWithView(Views.Full.class).writeValueAsString(yourEntity);

// 存数据库时脱敏序列化
ObjectMapper dbMapper = new ObjectMapper();
String dbSafeJson = dbMapper.writerWithView(Views.DatabaseSafe.class).writeValueAsString(yourEntity);

这种方案的好处是规则清晰,适合场景固定的情况,但如果你的系统中有很多类都包含敏感属性,一个个加@JsonView会有点繁琐。

2. 全局自动检测:BeanSerializerModifier

如果你想让Jackson自动识别所有包含特定敏感属性(比如命名为sensitiveProperties的字段,或者符合某种命名规则的属性)的类,并在存数据库时自动过滤,那可以用BeanSerializerModifier来全局修改序列化逻辑:

  • 自定义一个Modifier,检测类是否包含敏感属性,然后动态移除:
public class SensitivePropertyModifier extends BeanSerializerModifier {
    // 定义需要过滤的敏感属性名集合
    private static final Set<String> SENSITIVE_PROPS = Set.of("sensitiveProperty1", "sensitiveProperty2");

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
        // 检查当前类是否包含敏感属性
        boolean hasSensitiveProps = beanProperties.stream()
                .anyMatch(writer -> SENSITIVE_PROPS.contains(writer.getName()));
        
        if (hasSensitiveProps) {
            // 移除敏感属性
            beanProperties.removeIf(writer -> SENSITIVE_PROPS.contains(writer.getName()));
        }
        return beanProperties;
    }
}
  • 然后注册到ObjectMapper中,专门用于数据库序列化:
ObjectMapper dbMapper = new ObjectMapper();
dbMapper.registerModule(new SimpleModule() {
    @Override
    public void setupModule(SetupContext context) {
        context.addBeanSerializerModifier(new SensitivePropertyModifier());
    }
});

这种方案可以实现全局自动处理,不用给每个类加注解,适合批量处理多个类的场景。

3. 更灵活的动态过滤:@JsonFilter

如果你的敏感属性规则需要动态调整(比如不同环境过滤不同属性),可以用@JsonFilter来实现更灵活的全局过滤:

  • 首先定义一个过滤器:
public class SensitivePropertyFilter extends SimpleBeanPropertyFilter {
    private Set<String> excludedProps;

    public SensitivePropertyFilter(Set<String> excludedProps) {
        this.excludedProps = excludedProps;
    }

    @Override
    protected boolean include(BeanPropertyWriter writer) {
        return !excludedProps.contains(writer.getName());
    }
}
  • 给实体类加上@JsonFilter注解(或者全局注册过滤器,不用每个类加):
@JsonFilter("sensitiveFilter")
public class YourEntity {
    // 属性定义...
}
  • 序列化时动态指定要过滤的属性:
ObjectMapper dbMapper = new ObjectMapper();
FilterProvider filters = new SimpleFilterProvider()
        .addFilter("sensitiveFilter", new SensitivePropertyFilter(Set.of("sensitiveProperty1", "sensitiveProperty2")));
String dbSafeJson = dbMapper.writer(filters).writeValueAsString(yourEntity);

这种方案的优势是可以动态调整过滤规则,甚至在运行时修改要过滤的属性列表。

方案选择建议

  • 如果你的场景固定,只有少数几个类需要处理,优先用Jackson Views,代码可读性最高;
  • 如果有大量类需要统一过滤敏感属性,用BeanSerializerModifier实现全局自动处理;
  • 如果需要动态调整过滤规则,或者不同场景过滤不同属性,用**@JsonFilter**更灵活。

内容的提问来源于stack exchange,提问作者Alejandro Agapito Bautista

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:20:47