JavaScript解析JSON长数字精度丢失:如何保留原值并运算?
这是JavaScript里非常常见的精度坑——咱们先搞懂原因:JavaScript的Number类型是双精度浮点数,它能精确表示的最大整数是2^53(也就是9007199254740992),你的60000000000000012远远超过了这个安全范围,所以用JSON.parse解析时,会被自动转成不精确的Number,导致末尾的2被“吞”成0。
下面给你两种可行的解决方案,按需选择:
方案1:后端配合,把长数字存为字符串(最省心)
如果能控制JSON的生成逻辑,直接把这类超长ID改成字符串格式是最简单的:
{"messageType":"AddT","data":{"amount":0,"byUserID":2,"creationDate":1524572362828,"id":"60000000000000012"}}
解析后拿到字符串,后续要做算术运算时,用BigInt转换即可:
var str='{"messageType":"AddT","data":{"amount":0,"byUserID":2,"creationDate":1524572362828,"id":"60000000000000012"}}'; var js=JSON.parse(str); // 转成BigInt保留精度 const preciseId = BigInt(js.data.id); console.log(preciseId); // 输出 60000000000000012n // 算术运算示例(注意BigInt要和BigInt运算) const newId = preciseId + 10n; console.log(newId); // 60000000000000022n
方案2:自定义JSON解析器,自动转超长数字为BigInt
如果没法修改后端返回的JSON,就用JSON.parse的第二个参数——reviver函数,在解析过程中识别并转换超长整数:
var str='{"messageType":"AddT","data":{"amount":0,"byUserID":2,"creationDate":1524572362828,"id":60000000000000012}}'; var js=JSON.parse(str, (key, value) => { // 判断是否是超过安全范围的整数 if (typeof value === 'number' && Number.isInteger(value) && value > Number.MAX_SAFE_INTEGER) { return BigInt(value); } // 其他类型直接返回 return value; }); console.log(js.data.id); // 60000000000000012n // 做算术运算 console.log(js.data.id - 3n); // 60000000000000009n
额外注意事项
- BigInt不能直接被
JSON.stringify序列化,如果之后需要把数据转回JSON,要加个replacer函数处理:
const serializedStr = JSON.stringify(js, (key, value) => { return typeof value === 'bigint' ? value.toString() : value; });
- 要是需要兼容不支持BigInt的旧浏览器,可以用第三方库比如
decimal.js或者big-integer来处理大数字运算。
内容的提问来源于stack exchange,提问作者Karam Jabareen
相关产品推荐
相关产品推荐

