How to Implement Field-Level Data Desensitization with Jackson in Java
This tutorial explains how to move data desensitization to the JSON serialization stage using Jackson, defines a @Sensitive annotation, custom strategies, a contextual serializer, and demonstrates the approach with a User class example that masks personal fields during serialization.
Previously a MyBatis plugin was used for data desensitization, but it limited post‑query processing; moving the desensitization step to JSON serialization solves this problem.
Desensitization in Jackson Serialization
The transformation simply postpones desensitization to the JSON serialization phase using the Jackson library.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Sensitive {
SensitiveStrategy strategy();
}Desensitization strategies are defined as follows:
import java.util.function.Function;
/**
* Desensitization strategies.
*/
public enum SensitiveStrategy {
/** Username sensitive strategy. */
USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
/** ID card sensitive type. */
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1****$2")),
/** Phone sensitive type. */
PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
/** Address sensitive type. */
ADDRESS(s -> s.replaceAll("(\\S{3})\\S{2}(\\S*)\\S{2}", "$1****$2****"));
private final Function<String, String> desensitizer;
SensitiveStrategy(Function<String, String> desensitizer) {
this.desensitizer = desensitizer;
}
public Function<String, String> desensitizer() {
return desensitizer;
}
}Custom Desensitization Serializer
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import java.io.IOException;
import java.util.Objects;
/**
* @author felord.cn
* @since 1.0.8.RELEASE
*/
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {
private SensitiveStrategy strategy;
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(strategy.desensitizer().apply(value));
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
Sensitive annotation = property.getAnnotation(Sensitive.class);
if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass())) {
this.strategy = annotation.strategy();
return this;
}
return prov.findValueSerializer(property.getType(), property);
}
}The createContextual method obtains the @Sensitive annotation on a field and initializes the appropriate JsonSerializer; the serialize method applies the desensitization logic during JSON output.
Modified Sensitive Annotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveJsonSerializer.class)
public @interface Sensitive {
SensitiveStrategy strategy();
}Usage Example
@Data
public class User {
@Sensitive(strategy = SensitiveStrategy.USERNAME)
private String realName;
@Sensitive(strategy = SensitiveStrategy.ADDRESS)
private String address;
@Sensitive(strategy = SensitiveStrategy.PHONE)
private String phoneNumber;
@Sensitive(strategy = SensitiveStrategy.ID_CARD)
private String idCard;
} User user = new User();
user.setRealName("张三丰");
user.setPhoneNumber("13333333333");
user.setAddress("湖北省十堰市丹江口市武当山");
user.setIdCard("4333333333334334333");
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(user);
System.out.println(json); {
"realName":"张*丰",
"address":"湖北省****市丹江口市武****",
"phoneNumber":"133****3333",
"idCard":"4333****34333"
}The result shows successful field‑level masking; a switch could be added later to enable or disable desensitization based on context.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
