我有一些数字在json溢出的数字类型,所以我想要它是bigint,但如何?
{"foo":[[0],[64],[89],[97]],"bar":[[2323866757078990912,144636906343245838,441695983932742154,163402272522524744],[2477006750808014916,78818525534420994],[18577623609266200],[9008333127155712]]}
TLDR;
您可以使用JSON.parse()
reviver参数
详细解决方案要以这种方式控制JSON.parse()
的行为,您可以使用JSON.parse
(reviver
)的第二个参数-预处理键值对的函数(并且可能将所需的值传递给BigInt()
)。
然而,被识别为数字的值仍然会被强制(准确指出这个问题的功劳要归功于@YohanesGultom)。
为了解决这个问题,您可以在源JSON字符串中引用大数(将它们转换为字符串),以便在转换为bigint
时保留它们的值。
只要您希望仅将某些数字转换为bigint
,您就需要选择适当的标准(例如,检查Number.isSafeInteger()
的值是否超过Number.MAX_SAFE_INTEGER
,如@PeterSeliger所建议的)。
因此,你的问题可能会解决,像这样:
// source JSON string
const input = `{"foo":[[0],[64],[89],[97]],"bar":[[2323866757078990912,144636906343245838,441695983932742154,163402272522524744],[2477006750808014916,78818525534420994],[18577623609266200],[9008333127155712]]}`
// function that implements desired criteria
// to separate *big numbers* from *small* ones
//
// (works for input parameter num of type number/string)
const isBigNumber = num => !Number.isSafeInteger(+num)
// function that enquotes *big numbers* matching
// desired criteria into double quotes inside
// JSON string
//
// (function checking for *big numbers* may be
// passed as a second parameter for flexibility)
const enquoteBigNumber = (jsonString, bigNumChecker) =>
jsonString
.replaceAll(
/([:s[,]*)(d+)([s,]]*)/g,
(matchingSubstr, prefix, bigNum, suffix) =>
bigNumChecker(bigNum)
? `${prefix}"${bigNum}"${suffix}`
: matchingSubstr
)
// parser that turns matching *big numbers* in
// source JSON string to bigint
const parseWithBigInt = (jsonString, bigNumChecker) =>
JSON.parse(
enquoteBigNumber(jsonString, bigNumChecker),
(key, value) =>
!isNaN(value) && bigNumChecker(value)
? BigInt(value)
: value
)
// resulting output
const output = parseWithBigInt(input, isBigNumber)
console.log("output.foo[1][0]: n", output.foo[1][0], `(type: ${typeof output.foo[1][0]})`)
console.log("output.bar[0][0]: n", output.bar[0][0].toString(), `(type: ${typeof output.bar[0][0]})`)
.as-console-wrapper{min-height: 100% !important;}
注意:你可能会发现RegExp模式在JSON值中匹配数字字符串不是很健壮,所以你可以自由地提出你的(因为我的是我为了演示目的而最快地摘下来的)
注意:你仍然可以选择一些库,就像@YohanesGultom建议的那样,但是为了这个唯一的目的,在你的客户端包中添加10k或者在你的服务器端依赖项中添加37k(可能是docker图像大小)可能不太合理。
你可以试试我的库来解决这个问题:https://www.npmjs.com/package/json-with-bigint
的例子:
import { JSONParse } from 'json-with-bigint';
const yourJSON = `{"someValue":42,"someBigValue":10000000000000000365}`;
JSONParse(yourJSON); // { someValue: 42, someBigValue: 10000000000000000365n }
Library将自动计算BigInt
,因此不需要传递具有BigInt
值的特定键的列表。
还支持一致的往返操作(parse - stringify - parse)。反序列化的值将与最初序列化的值相同,反之亦然。
import { JSONParse, JSONStringify } from 'json-with-bigint';
const yourJSON = `{"someValue":42,"someBigValue":10000000000000000365}`;
JSONParse(yourJSON); // { someValue: 42, someBigValue: 10000000000000000365n }
JSONStringify(data); // '{"someValue":42,"someBigValue":10000000000000000365}'
JSONParse(JSONStringify(data)); // { someValue: 42, someBigValue: 10000000000000000365n }