当我尝试使用 Jackson 对象映射器将对象序列化为 JSON 时,它工作得很好。
{"id":1291741231928705024,"uuid":null,"email":"kannanrbk.r@gmail.com"}
然而,当我尝试使用 spring rest Controller 访问它时。长值数字四舍五入,即最后 3 位数字。
我阅读了 stackoverflow 中的现有问题,其中大多数建议将数据类型更改为字符串。但我们在大多数地方使用了 Long 值引用,更改数据类型将需要一些重构。
我做了初步分析:
- 我们正在使用 Jackson
ObjectMapper
- 它从 Spring 间接调用
MappingJackson2HttpMessageConverter
- 这个问题可能出在 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 确实截断:
但是“原始数据”选项卡正确显示数字:
在 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/