You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Protobuf int64转Scala Long时大数值传递出现异常变换问题

问题根因

首先排除Protobuf int64到Scala Long的转换问题:Protobuf对int64的二进制序列化基于变长64位整数编码实现,和Scala Long的内存布局完全匹配,不存在字节乱序、丢失的可能。
你遇到的是典型的大整数被转成双精度浮点数导致的精度丢失,核心逻辑如下:

  • 你的调用链路一定存在JSON序列化/反序列化环节(比如gRPC转HTTP JSON网关、前端/Node.js层传参、JSON格式的日志透传等),且处理client_id字段时,将64位整数按JSON的Number类型传输、解析。
  • JSON规范本身没有对Number类型的位宽做强制要求,但绝大多数JSON解析器、以及所有JavaScript运行环境,默认会把Number类型解析为IEEE 754双精度浮点数。这类浮点数最多只能精确表示53个二进制位对应的整数,精确表示的上限为9007199254740992(2^53,约16位十进制数)。
  • 当整数值超过253后,双精度浮点数的最小表示步长会从1开始随数值增大翻倍:数值在2602^61区间时步长为128,在2^632^64区间时步长为1024。如果传入的整数刚好是步长的整数倍,就能被精确传递(比如你测试通过的816645943620556288),否则会被自动舍入到最近的可表示值,就出现了你看到的末尾几位变动的现象。
  • 额外注意:你测试用的12550491997690948864已经超过了int64的最大合法取值9223372036854775807(2^63-1),就算精度不丢失,解析为有符号Long时也会出现溢出问题。
解决方案

根据你的链路情况选择对应方案即可:

  • 优先使用Protobuf二进制协议全链路调用,跳过JSON转码环节,从根源上避免浮点数精度问题。
  • 如果必须走JSON传输(比如前端调用、跨HTTP网关对接),打开Protobuf JSON序列化工具的int64序列化为字符串配置:所有64位整数在JSON中按字符串类型传输,接收端解析时再转回Long类型即可,不需要修改proto的字段定义。常用的ScalaPB、protobuf-java-util等库都原生支持该配置。
  • 检查链路中是否存在JavaScript/TypeScript编写的处理节点(前端页面、Node.js代理、网关JS插件等):这类环境原生没有64位整数类型,禁止用原生Number类型存储64位整数值,要么用字符串传递,要么使用BigInt类型处理。
  • 业务侧传入client_id时校验取值范围,不要超过int64的合法区间[-9223372036854775808, 9223372036854775807],避免溢出。

内容的提问来源于stack exchange,提问作者Jelly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 20:27:25