前言

JavaScript 中数字的精度是有限的,Java 的 Long 类型的数字超出了 JavaScript 的处理范围,只要 Java 传给 JavaScript 的 Long 类型的值超过 9007199254740991,就有可能产生精度丢失,从而导致数据和逻辑出错。解决办法之一就是让 JavaScript 把数字当成字符串进行处理,对 JavaScript 来说如果不进行运算,数字和字符串处理起来没有什么区别。

方法一、全局配置

在配置文件 application.yml 中增加配置:

  1. spring:
  2. jackson:
  3. generator:
  4. # 将所有的整数转化为字符串,解决整数过大前端精度丢失问题
  5. write_numbers_as_strings: true

该方法存在的问题

所有的数字类型都被序列为 String,包括 int 类型,粒度过大,加上此配置后前端会出现比较多的问题,例如分页组件。

方法二、使用注解

在字段上增加注解:

  1. @JsonSerialize(using=ToStringSerializer.class)
  2. private Long id;

该方法存在的问题

粒度太细,要在每个字段上增加注解,调整的代码量过大。

方法三、自定义 ObjectMapper 并排除特殊字段

到可以单独根据类型进行设置,只对 Long 型数据进行处理,转换成字符串,而对其他类型的数字不做处理,Jackson 提供了这种支持,方法是对 ObjectMapper 进行定制,SpringBoot 的官方文档
定制只针对 Long 类型进行处理:

  1. @Bean
  2. public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
  3. return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder
  4. .serializerByType(Long.class, ToStringSerializer.instance)
  5. .serializerByType(Long.TYPE, ToStringSerializer.instance);
  6. }

排除特殊的Long类型字段

对于部分 Long 类型的字段,如果转成字段串的话前端会出问题,例如分页查询时返回的总数不能转为字段串,否则前端分页插件无法正常工作。
增加对 Long 类型进行定义处理的 ObjectMapper

  1. public class LongJsonSerializer extends JsonSerializer<Long> {
  2. @Override
  3. public void serialize(Long value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
  4. throws IOException {
  5. if (value != null) {
  6. jsonGenerator.writeNumber(value);
  7. }
  8. }
  9. }

在字段上使用自定义序列化:

  1. @JsonSerialize(using = LongJsonSerializer.class)
  2. private long total;

参考:https://www.jianshu.com/p/f46699ea331a