Long 在 Swagger 中精度丢失

起因

某次通过 Swagger 在项目中进行测试的时候,发现响应体中返回的 id (Long 类型,由雪花算法生成) 与 数据库中存储的 id 始终差那么一点点。

排查

起先我认为是后端传得数据本身就有问题,于是我在 Controller 中进行返回数据的时候,将 id 的值 打印出来,发现 id 的值是正确的。于是我又在终端中单独执行了 curl 命令去获取数据,发现 id 的 值也是正确的。这时候我就很疑惑了,为什么在 Swagger 中获取的数据会有问题呢?

接着我猜测是出现了精度丢失的问题,我猜想 Long 类型可能不能完全在 js 中表示,于是 Swagger 在 对返回值进行解析的时候,不得不舍弃一部分。于是我通过关键字 Long 精度丢失 便找到了相关的内容:

JavaScriptNumber 类型是基于 IEEE 754 标准的双精度浮点数格式,只能安全地表示 53 位 二进制数字,也就是 Number.MAX_SAFE_INTEGER 的值 9007199254740991

解决方法

网上的解决方法有很多,例如可以通过在类中 Long 字段上添加 @JsonsSerialize(using = ToStringSerializer.class) 注解,将 Long 类型转换为 String 类型。

我并没有采取这样的解决方法,主要是考虑到还需要从请求体中接收参数,为了方便前端发送,我决定直接将 在从前端接收的 DTO 对象和发送给前端的 VO 对象中的 id 字段更改成 String 类型,然后在从 DTO 类型构造 PO 对象的时候,将 String 类型的 id 字段转换为 Long 类型,在从 PO 对象构造 VO 对象的时候,将 Long 类型的 id 字段转换为 String 类型。这样的好处在于,对于前端而言,id 确确 实实是一个 String 类型的字段,前端并不会知道 id 实际上是以 Long 类型进行存储的。

// 通过 UserPO 构造 UserVO
public UserVO(UserPO userPO) {
    this(userPO.getId().toString());
}

// 通过 UserDTO 构造 UserPO
public UserPO(UserDTO userDTO) {
    try {
        this.id = Long.valueOf(userDTO.id());
    } catch (NumberFormatException e) {
        this.id = null;
    }
}

巨人的肩膀




    Enjoy Reading This Article?

    Here are some more articles you might like to read next:

  • IEEE Xtreme 18.0 题解
  • 马拉松 4 小时挑战记录
  • ssh 端口转发简介
  • 服务器上创建 git 远程仓库
  • Spring Boot Test 自定义测试类顺序