Springboot返回给前端的Long类型数据失去精度
最近在写的一个项目后台 用到的实体类主键ID是用idworker生成的Long类型唯一id
由于之前一直用字符串id 所以突然发现Long类型数据通过JSON传到前端发生精度丢失
精度丢失
javascript 的 Number 类型最大长度是17位;
mysql 使用bigint 类型长度是20位;
我用到的idworker生成的id是19位的 刚好最后两位会凑整 也就是精度给我整没了
解决办法
我在项目用到的是mybatis-plus
下面列一些我的解决办法
把字段解析成字符串
用到了JsonFormat注解让对象属性在经过spring解析成JSON时直接转化成字符串
在要转的字段上加
/**
* 用户ID
*/
@TableId(value = "user_id", type = IdType.INPUT)
@JsonFormat(shape = JsonFormat.Shape.STRING)//转化成string传到前端
private Long userId;
这种方法我觉的不太好用 兄弟们实体类多的话那得一个一个加好麻烦
全局配置 把数字类型全部转化成字符串
在application.yml配置文件里加
spring:
jackson:
generator:
write-numbers-as-strings: true
这个方法我也不推荐 把所有数字都转成字符串了 分页之类要用到的integer啥的都不太方便
Jackson全局转化long类型为String
新建一个配置类
具体代码如下
@Configuration
public class JacksonConfig {
/**
* Jackson全局转化long类型为String,解决jackson序列化时传入前端Long类型缺失精度问题
*/
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
Jackson2ObjectMapperBuilderCustomizer cunstomizer = new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
// jacksonObjectMapperBuilder.serializerByType(BigInteger.class, ToStringSerializer.instance);
jacksonObjectMapperBuilder.serializerByType(Long.class, ToStringSerializer.instance);
// jacksonObjectMapperBuilder.serializerByType(Long.TYPE, ToStringSerializer.instance);
}
};
return cunstomizer;
}
}
这个方式我很推荐 只拦截对应的类型 兄弟们可以用起来
还有一些小细节想提一嘴
Long.class对应的是long的包装类Long,Long.TYPE对应的是基本数据类型long类型
如果你想拦截Long包装类类型的字段,不拦截基本数据类型long字段
除了在这个配置类里拦截外,你还得看你实体类的get方法返回值类型是什么,
因为Jackson转化是用get方法来获取值的,这里的拦截也是看get方法
举个例子
private Long userId;
public long getUserId(){
return this.userId
}
这样你的这个字段就没有被拦截还是数字到前端
因为你拦截的是Long类型 get方法返回的是long类型