如何使JSON.parse()将所有Numbers都视为BigInt?

e4eetjau  于 2023-03-24  发布在  其他
关注(0)|答案(1)|浏览(178)

我在json中有一些数字溢出了Number类型,所以我希望它是bigint,但是怎么做呢?

{"foo":[[0],[64],[89],[97]],"bar":[[2323866757078990912,144636906343245838,441695983932742154,163402272522524744],[2477006750808014916,78818525534420994],[18577623609266200],[9008333127155712]]}
mrfwxfqh

mrfwxfqh1#

TLDR;

您可以使用JSON.parse()reviver 参数

详细解决方案

要以这种方式控制JSON.parse()的行为,可以使用JSON.parsereviver)的第二个参数-预处理键值对的函数(可能会将所需的值传递给BigInt())。
然而,被识别为数字的值仍然会被“强制”(指出这个问题的功劳归于@YohanesGultom)。
为了解决这个问题,您可以在源JSON字符串中引用 big numbers(将它们转换为字符串),以便在转换为bigint时保留它们的值。
只要你只想将某些数字转换为bigint,你就需要选择适当的标准(例如,检查值是否超过Number.MAX_SAFE_INTEGERNumber.isSafeInteger(),正如@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镜像大小)可能并不十分合理。

相关问题