Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js JSON字符串化和PostgreSQL bigint遵从性_Node.js_Postgresql_Stringify_Bigint - Fatal编程技术网

Node.js JSON字符串化和PostgreSQL bigint遵从性

Node.js JSON字符串化和PostgreSQL bigint遵从性,node.js,postgresql,stringify,bigint,Node.js,Postgresql,Stringify,Bigint,,并在JSON.stringify中遇到问题 库的性质允许不必担心类型歧义和反序列化,因为所有序列化的内容都会进入服务器,并且不需要任何反序列化 我最初提出了以下简化方法,只是为了抵消Node.js抛出的TypeError:不知道如何对我的BigInt进行序列化: // Does JSON.stringify, with support for BigInt: function toJson(data) { return JSON.stringify(data, (_, v) =>

,并在JSON.stringify中遇到问题

库的性质允许不必担心类型歧义和反序列化,因为所有序列化的内容都会进入服务器,并且不需要任何反序列化

我最初提出了以下简化方法,只是为了抵消Node.js抛出的
TypeError:不知道如何对我的BigInt进行序列化:

// Does JSON.stringify, with support for BigInt:
function toJson(data) {
    return JSON.stringify(data, (_, v) => typeof v === 'bigint' ? v.toString() : v);
}
但由于它将每个
BigInt
转换为字符串,因此每个值最终都会被包装成双引号

在Node.js格式化实用程序中是否有任何解决方法(可能是一些技巧)可以从
JSON.stringify
生成一个结果,其中每个
BigInt
都将格式化为一个打开的值?这是PostgreSQL理解和支持的,因此我正在寻找一种使用
BigInt
生成JSON的方法,该方法与PostgreSQL兼容

示例

const obj = {
    value: 123n
};

console.log(toJson(obj));

// This is what I'm getting: {"value":"123"}
// This is what I want: {"value":123}
显然,我不能将
BigInt
转换成
number
,因为那样我就会丢失信息。为此重写整个
JSON.stringify
可能太复杂了

更新

此时,我已经回顾并使用了几种多边形填充,如以下:


但它们似乎都是一个笨拙的解决方案,引入这么多代码,然后修改以获得
BigInt
支持。我希望找到更优雅的解决方案。

我最终得到的解决方案

注入完整的
123n
数字,然后在RegEx的帮助下取消引用这些数字:

function toJson(data) {
    return JSON.stringify(data, (_, v) => typeof v === 'bigint' ? `${v}n` : v)
        .replace(/"(-?\d+)n"/g, (_, a) => a);
}
它能做需要的事情,而且速度很快。唯一的缺点是,如果您的
数据中有一个值设置为类似
123n
的字符串,它将成为一个开放数字,但您可以很容易地将其混淆为类似
${^123^}
123 bigint
的内容,该算法很容易实现

根据这个问题,该操作并不意味着是可逆的,因此如果对结果使用
JSON.parse
,这些结果将是
number
-s,正如预期的那样,丢失
2^53
2^64-1
之间的任何内容

谁说这是不可能的-嗯?:)

更新-1

为了与
JSON.stringify
兼容,
未定义
必须导致
未定义
。在实际实现中,我现在使用了
“123#bigint”
模式,以减少意外匹配的可能性

下面是最后的代码:

 function toJson(data) {
    if (data !== undefined) {
        return JSON.stringify(data, (_, v) => typeof v === 'bigint' ? `${v}#bigint` : v)
            .replace(/"(-?\d+)#bigint"/g, (_, a) => a);
    }
}
更新-2

查看下面的注释,您可以通过计算与
BigInt
注入匹配的替换数量,并在出现不匹配时抛出错误来确保安全:

function toJson(data) {
    if (data !== undefined) {
        let intCount = 0, repCount = 0;
        const json = JSON.stringify(data, (_, v) => {
            if (typeof v === 'bigint') {
                intCount++;
                return `${v}#bigint`;
            }
            return v;
        });
        const res = json.replace(/"(-?\d+)#bigint"/g, (_, a) => {
            repCount++;
            return a;
        });
        if (repCount > intCount) {
            // You have a string somewhere that looks like "123#bigint";
            throw new Error(`BigInt serialization conflict with a string value.`);
        }
        return res;
    }
}

虽然我个人认为这是一种过火的做法,而且
UPDATE-1
中的方法已经足够好了。

我也不认为用原生
JSON.stringify
实现这一点的方法(除此之外)。我很确定,通过剥离不必要的功能(缩进、ES3兼容性),可以大大简化polyfills的代码。@Bergi我一直在得出相同的结论,但仍然希望是错误的,以避免混淆polyfills的修改。由于这个东西非常通用,它会要求自己的包,我想。@Bergi看到了我自己的答案,在我得到了所有“不可能的”反馈之后:))我建议采用@Melchia的方法,让
toJson
回调返回一个类似
{“$type”:“bigint”,“value:”…
,然后将其与正则表达式匹配。这将使意外匹配几乎不可能。JSON很可能包含用户控制的任意字符串数据,这些数据可以通过手工制作来进行注入,而完整的对象由用户控制则是很不寻常的。@Bergi实际上,他的建议毫无意义,因为它没有解决任何问题。他根本没有建议使用正则表达式。现在我使用的是
“123#bigint”
,它足够独特,不会与随机字符串混合。我认为把它转换成一个对象并没有什么好处。它将以相同的字符串结尾,对于ReGEX进行解析是更复杂的。不同之处在于,我认为…也许它不太可能随机出现,但对于控制对象中某些字符串值的攻击者来说,它似乎很容易注入。正则表达式会更长,是的,但不会更复杂。作为一种额外的安全措施,您可以添加一个计数器,用于计算在对象中遇到多少个bigint,以及另一个计数器,用于计算应用
replace
回调的频率,如果不匹配,则抛出异常,而不是在数据库中存储无效数据。@Bergi在替换计数不匹配时抛出错误实际上是个好主意。早些时候我自己也在考虑。