long类型的id属性传到前端会精度丢失的解决方案

记录一个前段时间使用雪花算法时候遇到的坑。

场景大概是这样的:
我有一个设备信息实体类,设备id是 long 类型,映射到数据库中是一个设备表,主键id是 bigint 类型。id的生成策略是使用雪花算法。

使用postman调用接口,获取到的JSON是正常的

{
  "id": 1297873308628307970,
  ...
  //其他属性省略
}

但是到了前端那边id的值却变成了1297873308628300000
仔细一比较发现这两个数值还挺像的,只有后4位不一样,当时立马想到了是不是精度丢失。
那么在哪个环节丢失了精度?用postman获取JSON的时候,数值是正常的,那么肯定不是后端丢失了精度,只可能是前端那边丢失了精度。

上网查了下,JSON字符串转JS对象,JSON中的数字会转为 number 类型, number 类型的精度是16位,但是雪花算法生成的id长度有19位,so后面的几位精度就丢失了。如果想要前端不丢失精度,JSON中的id就不能是long类型,改为String类型就好了。

问题找到了,但要怎么解决呢。一种方案是修改实体类中id的类型,将id改为String类型,并且将表的主键也改为varchar类型。但是字符串查询性能比数字差,所以这种方案不太推荐。

好在Jackson已经为我了提供了三种方案
一种是直接在实体类的id属性上面加上注解 @JsonSerialize(using = ToStringSerializer.class)
这样一来,在后端依然是 long 类型,当实体类序列化成JSON的时候,在JSON中这个属性就会变成string类型。

上面这种办法有个缺点就是,如果有很多的实体类的id都是 long 类型,那就得给每一个都加上注解,这样未免有些麻烦。下面这个方法通过添加一个全局配置来使long类型转为JSON中的string类型,省去了一个一个添加注解的麻烦。

@Configuration
public class JacksonConfig {
  @Bean
  @Primary
  @ConditionalOnMissingBean(ObjectMapper.class)
  public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder)
  {
    ObjectMapper objectMapper = builder.createXmlMapper(false).build();
    // 全局配置序列化返回 JSON 处理
    SimpleModule simpleModule = new SimpleModule();
    //JSON Long ==> String
    simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
    objectMapper.registerModule(simpleModule);
    return objectMapper;
  }
}

第三种办法是在application.yml中加上以下配置,这个办法会将所有数字都变成字符串,包括longint 类型

spring:
  jackson:
    generator:
      writeNumbersAsStrings: true
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值