基于Jackson ObjectMapper实现无注解通用JSON掩码的方案问询
Jackson ObjectMapper实现无注解字段名掩码方案
Jackson提供了完善的扩展钩子机制,可以满足你在首次序列化时基于字段名自动完成掩码的需求,无需业务代码添加注解。核心是通过**自定义BeanSerializerModifier和JsonSerializer**来实现,具体步骤如下:
核心扩展组件
1. 自定义掩码序列化器
实现JsonSerializer,封装不同字段的掩码逻辑:
// 掩码策略接口,定义不同字段的掩码规则 public interface MaskStrategy { String mask(String original); } // 手机号掩码实现示例 public class PhoneMaskStrategy implements MaskStrategy { @Override public String mask(String original) { return original.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"); } } // 邮箱掩码实现示例 public class EmailMaskStrategy implements MaskStrategy { @Override public String mask(String original) { return original.replaceAll("(^[^@]{3})[^@]+@", "$1***@"); } } // 通用掩码序列化器 public class MaskingSerializer extends JsonSerializer<Object> { private final MaskStrategy strategy; public MaskingSerializer(MaskStrategy strategy) { this.strategy = strategy; } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { if (value == null) { gen.writeNull(); return; } // 对非字符串类型先转为字符串再掩码 String maskedValue = strategy.mask(value.toString()); gen.writeString(maskedValue); } }
2. 自定义SerializerModifier
通过BeanSerializerModifier拦截序列化过程,根据字段名替换对应的序列化器:
public class MaskingSerializerModifier extends BeanSerializerModifier { private final Map<String, MaskStrategy> fieldMaskMapping; public MaskingSerializerModifier(Map<String, MaskStrategy> fieldMaskMapping) { this.fieldMaskMapping = fieldMaskMapping; } @Override public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) { if (!(serializer instanceof BeanSerializer)) { return super.modifySerializer(config, beanDesc, serializer); } BeanSerializer beanSerializer = (BeanSerializer) serializer; List<BeanPropertyWriter> propertyWriters = new ArrayList<>(beanSerializer.getProperties()); for (int i = 0; i < propertyWriters.size(); i++) { BeanPropertyWriter writer = propertyWriters.get(i); String fieldName = writer.getName(); // 匹配掩码字段映射表,替换为自定义序列化器 if (fieldMaskMapping.containsKey(fieldName)) { MaskStrategy strategy = fieldMaskMapping.get(fieldName); propertyWriters.set(i, new MaskingPropertyWriter(writer, new MaskingSerializer(strategy))); } } // 返回修改后的BeanSerializer return beanSerializer.withProperties(propertyWriters); } // 包装BeanPropertyWriter,替换字段序列化逻辑 private static class MaskingPropertyWriter extends BeanPropertyWriter { private final JsonSerializer<Object> maskingSerializer; public MaskingPropertyWriter(BeanPropertyWriter baseWriter, JsonSerializer<Object> maskingSerializer) { super(baseWriter); this.maskingSerializer = maskingSerializer; } @Override public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { Object fieldValue = get(bean); if (fieldValue != null) { gen.writeFieldName(_name); maskingSerializer.serialize(fieldValue, gen, prov); return; } // 字段值为空时沿用原有逻辑 super.serializeAsField(bean, gen, prov); } } }
3. 配置自定义ObjectMapper(Spring Boot场景)
将自定义的SerializerModifier注册到ObjectMapper中,并通过自动配置让其全局生效:
@Configuration public class MaskingAutoConfiguration { @Bean public Jackson2ObjectMapperBuilderCustomizer maskingJacksonCustomizer() { // 构建字段名与掩码策略的映射表 Map<String, MaskStrategy> fieldMaskMap = new HashMap<>(); fieldMaskMap.put("phone", new PhoneMaskStrategy()); fieldMaskMap.put("email", new EmailMaskStrategy()); fieldMaskMap.put("idCard", original -> original.replaceAll("(\\d{6})\\d{8}(\\d{4})", "$1********$2")); // 可根据需求添加更多字段映射 return builder -> builder.modules(new SimpleModule() .setSerializerModifier(new MaskingSerializerModifier(fieldMaskMap))); } }
方案优势
- 无侵入性:无需业务代码添加任何注解,完全在框架层实现,对开发人员透明
- 性能优化:直接在首次序列化过程中处理,避免了先转Map再遍历修改的额外开销
- 扩展性强:可通过修改
fieldMaskMap灵活添加/调整字段的掩码策略,适配不同业务场景
内容的提问来源于stack exchange,提问作者matthenry87
相关产品推荐
相关产品推荐

