后端返回 id=1289891059652632577,结果前端一直接收到id=1289891059652632600,排查了好久,原来是 JS 的 Number 类型的精度问题。

JS 的 Number 类型的最大安全值

JS 的 Number 类型的最大安全值为:

2531=900719925474099212^{53}-1=9007199254740992-1

即安全值的返回是:

1
2
Number.MIN_SAFE_INTEGER ~ Number.MAX_SAFE_INTEGER
(-9007199254740991 ~ 9007199254740991)

超过这个值,Number 类型会出现异常。

BigInt

针对这个问题,JavaScript 设计了一个新的原始类型,可以表示任意精度的整数,包括超过安全值的范围。

使用方式是将 数值后加 n

9007199254740992n+1n=9007199254740993n9007199254740992n + 1n = 9007199254740993n

BigInt 的更多介绍

解决方案

Java 中 Long 会出现问题,考虑将 Json 中的所有 Long 字段转为 String

可以使用下面的代码进行配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package A;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@JsonComponent
public class JsonSerializerConfig {

@Bean
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
//忽略value为null 时 key的输出
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
/*
* 序列换成json时,将所有的long变成string
* 因为js中得数字类型不能包含所有的java long值
*/
SimpleModule module = new SimpleModule();
module.addSerializer(Long.class, ToStringSerializer.instance);
module.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(module);
return objectMapper;
}

}