Information Security 7 min read

Java Data Desensitization with Hutool and Custom Jackson Serializer

The article demonstrates how to mask sensitive Java backend data by using Hutool's DesensitizedUtil for common types and a custom @Desensitization annotation with a DesensitizationTypeEnum‑driven Jackson serializer (or Fastjson ValueFilter) to apply flexible masking rules during JSON serialization.

Java Tech Enthusiast
Java Tech Enthusiast
Java Tech Enthusiast
Java Data Desensitization with Hutool and Custom Jackson Serializer

This article explains how to mask sensitive data in Java backend responses using Hutool's DesensitizedUtil and custom Jackson serialization.

Common desensitization methods such as replacement, deletion, reordering, and noise addition are listed, with replacement being the most frequently used.

Using Hutool, you can directly call DesensitizedUtil for types like user ID, Chinese name, ID number, phone, email, and bank card.

For a more flexible solution, a custom annotation @Desensitization is defined, which references a DesensitizationTypeEnum to specify the masking rule.

The annotation is processed by a custom serializer DesensitizationSerialize that implements JsonSerializer and ContextualSerializer . The serializer switches on the enum to apply the appropriate masking logic.

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizationSerialize.class)
public @interface Desensitization {
    DesensitizationTypeEnum type() default DesensitizationTypeEnum.MY_RULE;
    int startInclude() default 0;
    int endExclude() default 0;
}

The enum can contain custom masking implementations, eliminating the need for switch‑case statements:

public enum DesensitizationTypeEnum {
    MY_RULE {
        @Override
        public String desensitize(String str, Integer start, Integer end) {
            return StrUtil.hide(str, start, end);
        }
    },
    USER_ID {
        @Override
        public String desensitize(String str, Integer start, Integer end) {
            return String.valueOf(DesensitizedUtil.userId());
        }
    },
    MOBILE_PHONE {
        @Override
        public String desensitize(String str, Integer start, Integer end) {
            return String.valueOf(DesensitizedUtil.mobilePhone(str));
        }
    },
    EMAIL {
        @Override
        public String desensitize(String str, Integer start, Integer end) {
            return String.valueOf(DesensitizedUtil.email(str));
        }
    };
    public abstract String desensitize(String str, Integer start, Integer end);
}

Apply the annotation on model fields:

@Data
public class User {
    @Desensitization(type = DesensitizationTypeEnum.MY_RULE, startInclude = 4, endExclude = 7)
    private String userid;

    @Desensitization(type = DesensitizationTypeEnum.MOBILE_PHONE)
    private String phone;

    @Desensitization(type = DesensitizationTypeEnum.EMAIL)
    private String email;
}

When serialized to JSON, the output masks the data, e.g.:

{
  "userid": "user***56",
  "phone": "181****8155",
  "email": "***********@163.com"
}

If Fastjson is used instead of Jackson, a custom ValueFilter can be created to perform the same masking.

JavaSpring BootHutoolJacksonData Desensitization
Java Tech Enthusiast
Written by

Java Tech Enthusiast

Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.