前言
JavaScript 中数字的精度是有限的,Java 的 Long 类型的数字超出了 JavaScript 的处理范围,只要 Java 传给 JavaScript 的 Long 类型的值超过 9007199254740991,就有可能产生精度丢失,从而导致数据和逻辑出错。解决办法之一就是让 JavaScript 把数字当成字符串进行处理,对 JavaScript 来说如果不进行运算,数字和字符串处理起来没有什么区别。
方法一、全局配置
在配置文件 application.yml
中增加配置:
spring:
jackson:
generator:
# 将所有的整数转化为字符串,解决整数过大前端精度丢失问题
write_numbers_as_strings: true
该方法存在的问题
所有的数字类型都被序列为 String
,包括 int
类型,粒度过大,加上此配置后前端会出现比较多的问题,例如分页组件。
方法二、使用注解
在字段上增加注解:
@JsonSerialize(using=ToStringSerializer.class)
private Long id;
该方法存在的问题
方法三、自定义 ObjectMapper 并排除特殊字段
到可以单独根据类型进行设置,只对 Long 型数据进行处理,转换成字符串,而对其他类型的数字不做处理,Jackson
提供了这种支持,方法是对 ObjectMapper
进行定制,SpringBoot 的官方文档。
定制只针对 Long 类型进行处理:
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder
.serializerByType(Long.class, ToStringSerializer.instance)
.serializerByType(Long.TYPE, ToStringSerializer.instance);
}
排除特殊的Long类型字段
对于部分 Long
类型的字段,如果转成字段串的话前端会出问题,例如分页查询时返回的总数不能转为字段串,否则前端分页插件无法正常工作。
增加对 Long
类型进行定义处理的 ObjectMapper
:
public class LongJsonSerializer extends JsonSerializer<Long> {
@Override
public void serialize(Long value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
if (value != null) {
jsonGenerator.writeNumber(value);
}
}
}
在字段上使用自定义序列化:
@JsonSerialize(using = LongJsonSerializer.class)
private long total;