You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
前端往后端 POST 数据时,有两种常见的编码形式 application/x-www-form-urlencoded 和 application/json 。
当需要传递一个 number 类型的 id 给接口时,application/x-www-form-urlencoded 在 HTTP Request Body 中传输的是 id=1,而 application/json 的 Body 则是 {"id":1} 。之所以认为后者的语义更好,是因为后者能正确地反映出 id 的真实类型为 number。
而当这个 id 为 String 类型时,前者传输的依然是 id=1,后者则变为了 {"id":"1"}。对于后端程序来说,这层类型语义能让参数类型校验和计算更加准确和方便。
Uh oh!
There was an error while loading. Please reload this page.
双精度浮点数
JavaScript 采用双精度浮点数( IEEE 754 标准)来表示它的 Number 类型。一个数字占用 64 bits 存储空间(这里的每一位都只能存放 0 或 1):
最大安全整数
当表示整数时,js只使用52位尾数来表示,最大为2^53-1,即
9007199254740991
,超过这个数就会发生进位溢出等错误。后端大数传输问题
而后端如果采用bigint 类型字段,在 MySQL 中,一个 bigint 存储占用 8 Bytes 的空间,即 64 bits。当取值为无符号整型时,能表示的范围是 0 到 2 的 64^-1,即
18446744073709551615
。当取值在 (9007199254740991, 18446744073709551615] 之间时,后端程序通常能正确的执行 JSON 序列化操作,并通过 HTTP 接口返回给前端,而前端执行
JSON.parse
解码时,会因为语言本身的限制发生精度丢失,引发 bug。大数转字符串类型
为了解决大数传递精度丢失的问题,常见的方案是“将大数转为字符串类型”。具体的做法如下:
一些第三方库(如 json-bigint)之所以能正确的处理大数 parse ,且不造成精度丢失,其实现原理也是类似。
类型语义丢失
上述处理其实会带来string和number类型混乱问题,无法得知当前传递的数据到底是以string类型,还是要以大数类型处理。
前端往后端 POST 数据时,有两种常见的编码形式
application/x-www-form-urlencoded
和application/json
。当需要传递一个 number 类型的 id 给接口时,application/x-www-form-urlencoded 在 HTTP Request Body 中传输的是
id=1
,而 application/json 的 Body 则是{"id":1}
。之所以认为后者的语义更好,是因为后者能正确地反映出 id 的真实类型为 number。而当这个 id 为 String 类型时,前者传输的依然是
id=1
,后者则变为了{"id":"1"}
。对于后端程序来说,这层类型语义能让参数类型校验和计算更加准确和方便。而如果前后端采用将“大数转为字符串”的方案,当 taskid 以 string 类型返回时,调用方将无法判断出它在业务和 DB 中到底是 char 字符类型存储的,还是 bigint 类型存储,导致类型语义丢失的情况发生。
参考文章:JSON Bigint大数精度丢失的背后
The text was updated successfully, but these errors were encountered: