java - 诡异的! Spring Boot 中的长值舍入问题

标签 java spring spring-boot jackson

当我尝试使用 Jackson 对象映射器将对象序列化为 JSON 时,它工作得很好。

 {"id":1291741231928705024,"uuid":null,"email":"kannanrbk.r@gmail.com"}

然而,当我尝试使用 spring rest Controller 访问它时。长值数字四舍五入,即最后 3 位数字。

enter image description here

我阅读了 stackoverflow 中的现有问题,其中大多数建议将数据类型更改为字符串。但我们在大多数地方使用了 Long 值引用,更改数据类型将需要一些重构。

我做了初步分析:

  1. 我们正在使用 Jackson ObjectMapper
  2. 它从 Spring 间接调用 MappingJackson2HttpMessageConverter
  3. 这个问题可能出在 JSONParser 附近,它将任何数字视为 double (15 位数字),然后四舍五入

有什么办法可以解决这个问题吗?

最佳答案

Is there any way to fix this issue?

Jackson/Java/Spring Boot没问题,JavaScript/Browser没问题。

为了重现这个问题,我序列化了同一个对象并使用 curl 得到了这个:

$ curl localhost:8080
{"id":1291741231928705024,"uuid":null,"email":"kannanrbk.r@gmail.com"}

此处数字已正确序列化。

在 Firefox 中查看的相同 json 确实截断:

Truncated value in Firefox (JSON tab)

但是“原始数据”选项卡正确显示数字:

Correct value displayed in Firefox ("Raw Data tab")

在 JavaScript 中 1291741231928705024 不是安全整数(参见 Number.isSafeInteger() ):

Number.isSafeInteger(1291741231928705024);
false

数字大于 2^53 - 1 所以它被四舍五入。在 JavaScript 中可能出现更令人困惑的情况:

> 1291741231928705024 === 1291741231928705022
true

可能的解决方案

首先检查您的客户是否存在此类问题。如果它可以安全地反序列化这些数字,那么您就安全了。

或者你可以long 序列化为 String(正如你在问题中提到的),这就是 Twitter 在其 Twitter IDs (snowflake) 中提出的建议文章:

To allow Javascript and JSON parsers to read the IDs, Twitter objects include a string version of any ID when responding with JSON. Status, User, Direct Message, Saved Search and other IDs in the Twitter API are therefore returned as both an integer and a string in JSON responses.

关于java - 诡异的! Spring Boot 中的长值舍入问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63362205/

相关文章:

java - Spring Data JPA findAll 与不同的EntityGraph

java - Bootstrap 的导航栏模板显示不正确的布局

java - 可以从 null 转换为 int 吗?

Java:希望忽略某些超出范围的行

java - 在 lambda aws 测试期间,抛出类未找到异常

java - Spring Security 空指针异常

java - HttpClientErrorException : 404 null

java - 基于自定义属性的 Spring Boot SOAP Web 服务的 Keycloak 身份验证

java - 从命令行使用 Ivy 时,如何让 Ivy 将依赖项复制到 lib 目录?

java - 使用通用类型