前言
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 类型进行处理:
@Beanpublic 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> {@Overridepublic void serialize(Long value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)throws IOException {if (value != null) {jsonGenerator.writeNumber(value);}}}
在字段上使用自定义序列化:
@JsonSerialize(using = LongJsonSerializer.class)private long total;
