基于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
相关产品推荐
相关产品推荐

