js的数据精度问题

前后端数值传递中的 js数值精度损失问题

问题图示:

原数值

后端传递的值为1176037389258023221

接收值
js接收到的值为:1176037389258023200

产生原因:

JavaScript的Number类型能表示并进行精确算术运算的安全整数范围为:正负2^53^-1,16位数

所以对于后台的long类型数据,在数值过大时,就会出现精度损失。

解决方案:

由于接收时的数据就是损失状态,所以不好在js中直接处理,当然,也有一些方式能够解决这个问题。比如jison,通过它可以对要接收的数据的重新定义json parser

不过,这种情况一般都会交给后端解决,让传递的值转为字符串,这样就不会有精度损失的问题。

后端(java)解决方式示例:

①使用@JsonSerialize注解,作用于实例域的Get方法,在数据输出时将其转为字符串,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package cn.shirtiny.community.SHcommunity.DTO;

import ...

@Data
public class InvitationDTO {
//输出时转字符串
@JsonSerialize(using = ToStringSerializer.class)//作用于属性的get方法
private long invitationId;//主键id
//输出时转字符串
@JsonSerialize(using = ToStringSerializer.class)
private long authorId; //作者id
@JsonSerialize(using = ToStringSerializer.class)
private long gmtCreate;//作者的注册时间
}

②直接将DTO对象关于Long类型的属性,设为String类型,在与数据库交互时,进行类型转换:

1
2
3
4
5
6
7
8
9
10
package cn.shirtiny.community.SHcommunity.DTO;

import ...

@Data
public class InvitationDTO {
private String invitationId;//主键id
private String authorId; //作者id
private String gmtCreate;//作者的注册时间
}

注:如果需要字符串类型的uuid,可以使用以下方式,在mapper里写

1
2
3
4
> // 返回String类型的UUID
> @Select("SELECT UUID_SHORT()")
> String getShortStrUUid();
>