问题描述
后端把Long类型的数据传给前端,前端可能会出现精度丢失的情况。例如:201511200001725439这样一个Long类型的整数,传给前端后会变成201511200001725440
相关概念
javaScript
的最大安全值:Number.MAX_SAFE_INTEGER 是一个值为 9007199254740991 的常量。因为 javaScript
的数字存储使用了 IEEE 754 中规定的 双精度浮点数 数据类型,而这一数据类型能够安全存储 -(2^53 - 1)
到 2^53 - 1 之间的数值(包含边界值)。
// 也即 -(Math.pow(2, 53) - 1) 到 (Math.pow(2, 53) - 1),即 -9007199254740991 到 9007199254740991之间的数值(包含边界值)
这里安全存储的意思是指能够准确区分两个不相同的值,例如
Number.MAX_SAEF_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 将得到 true 的结果,而这在数学上是错误的
下图可以看出,输入的值超出安全值,可能会被js自动转化
img另外,javaScript
的最大值: Number.MAX_VALUE 其值为 1.7976931348623157e+308,代表js可表示的最大值,使用时可用来判断某个值是否超出了 js 可表示的最大值
场景还原
使用 nodejs
起一个服务, 然后传给前端一个Long类型的数值
const http = require('http')
const onRequest = function (request, response) {
console.log('---Request received---')
response.writeHead(200, {
'Content-Type': 'application/json'
})
var data = {
number: 201511200001725439 // (*)
}
response.end(JSON.stringify(data))
}
const server = http.createServer(onRequest)
server.listen(3000, '127.0.0.1')
console.log('Server started on localhost port 3000')
访问 localhost:3000
{
"number": 201511200001725440
}
发现我们前端得到的数值和后端原本设置的数值不一样
解决方案一
在后台将这个Long类型的字段转换成String类型的,风险比较大
const http = require('http')
const onRequest = function (request, response) {
console.log('---Request received---')
response.writeHead(200, {
'Content-Type': 'application/json'
})
var data = {
number: '201511200001725439' // (*) // string
}
response.end(JSON.stringify(data))
}
const server = http.createServer(onRequest)
server.listen(3000, '127.0.0.1')
console.log('Server started on localhost port 3000')
再次访问
{
"number": "201511200001725439"
}
这回发现前后端的数据完全一致,没有出现精度丢失
解决方案二
使用 fastjson
的提供的注解,@JSONField(serializeUsing= ToStringSerializer.class)