Solve Long Precision Loss in Spring Boot 3 with Jackson and Custom Annotations
This article demonstrates how to handle Java Long precision loss in Spring Boot 3 front‑end displays, configures Jackson to serialize Long as String, uses @JsonValue for single‑property serialization, and creates custom annotations with a SensitiveSerializer for data masking, complete with code examples and screenshots.
In previous articles we introduced extensive Jackson usage in Spring Boot. This article focuses on two main topics: Long precision loss in the front‑end and @JsonValue serialization of single property values, plus the creation of custom annotations for sensitive data masking.
1. Introduction
The following topics are covered:
Long type precision loss in the front‑end
@JsonValue serialization of single property values
Custom annotation application
2. Practical Cases
2.1 Long Precision Loss
When JavaScript handles large numbers such as Java Long, precision can be lost because JavaScript uses IEEE‑754 64‑bit floating‑point numbers, which cannot accurately represent integers larger than 2^53‑1. The following controller returns a 17‑digit Long value:
@RestController
@RequestMapping("/longs")
public class LongController {
@GetMapping("")
public Map<String, Object> getData() {
return Map.of("code", 0, "data", 123456789012345678L);
}
}Directly accessing the endpoint in a browser shows the correct value, but the network response contains the truncated number. An Ajax request also returns the incorrect value:
function getData() {
axios.get('http://localhost:8080/longs')
.then(resp => {
console.log(resp.data);
}).catch(error => {
console.log(error);
});
}To prevent this issue, configure Jackson to serialize all Long values as String globally:
@Component
public class PackMapperCustomizer implements Jackson2ObjectMapperBuilderCustomizer {
@Override
public void customize(Jackson2ObjectMapperBuilder builder) {
builder.serializerByType(Long.class, ToStringSerializer.instance);
}
}If only specific fields need conversion, annotate them with @JsonSerialize(using = ToStringSerializer.class):
public class User {
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
private String name;
// getters, setters
}2.2 @JsonValue Serialization of Single Property Values
The @JsonValue annotation marks a method or field whose value will be used as the JSON representation of the entire object. For example, an enum:
public enum PaymentStatus {
NO_PAY(0, "未支付"), PAID(1, "已支付");
private Integer code;
private String desc;
// constructor, getters, setters
}When the enum is returned from a controller, the default JSON output is the enum name. Adding @JsonValue to a field makes that field the JSON value:
@JsonValue
private String desc;Applying @JsonValue to a regular bean field yields the same effect:
public class User {
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@JsonValue
private String name;
}2.3 Custom Annotation for Sensitive Data Masking
To mask sensitive fields such as ID cards or phone numbers, define a custom annotation using @JacksonAnnotationsInside and a serializer:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveSerializer.class)
public @interface Sensitive {
int start() default 0;
int end() default 0;
String mask() default "*";
}The corresponding serializer implements the masking logic:
public class SensitiveSerializer extends JsonSerializer<String> implements ContextualSerializer {
private Sensitive sensitive;
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
String val = value;
if (sensitive != null && StringUtils.hasLength(val)) {
String m = sensitive.mask();
int start = sensitive.start();
int end = sensitive.end();
int totalLength = value.length();
// masking algorithm omitted for brevity
}
gen.writeString(val);
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
sensitive = property.getAnnotation(Sensitive.class);
return this;
}
}Use the annotation on fields that require masking:
public class User {
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
private String name;
@Sensitive(start = 6, end = 4)
private String idCard;
@Sensitive(start = 4, end = 3)
private String phone;
// getters, setters
}The front‑end now displays masked values for the annotated fields.
Overall, the article provides practical solutions for Long precision handling, single‑property JSON serialization, and custom data masking in Spring Boot 3 applications.
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.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
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.
