强制 JSON.stringify() 发出这样做的 NaN / Infinity 或 JS JSON 库

Posted

技术标签:

【中文标题】强制 JSON.stringify() 发出这样做的 NaN / Infinity 或 JS JSON 库【英文标题】:Force JSON.stringify() to emit NaN / Infinity or JS JSON lib that does so 【发布时间】:2014-03-20 17:54:07 【问题描述】:

我正在研究将 NaN/Infinity 支持添加到使用 JSONRPC 进行客户端/服务器交互的现有科学应用程序的可行性。许多 JSON 库确实(在某些情况下可选)处理 NaN 和 Inf,例如:

Python json 读写 Java Jackson 读取但写入字符串而不是裸字 Java GSON 读写 javascript 可以read

我知道 JSON spec 不支持 NaN 和 Infinity,并且知道 related questions。但是,AFAICT 是否有某种方式可以强制原生 JS JSON.stringify() 方法发出 NaN/Infinity,或者是否有一个 JS JSON 库可以做到这一点,这个问题没有得到解答。与引用的问题可能存在细微差别,但很重要。到目前为止,我一直无法发现这样的方法或库,所以我在这里。编写自己的 JSON 序列化程序是唯一的选择吗?

请注意,JSON.stringify()replacement 参数没有帮助,至少在我手中是这样。

更新: 将 NaN/Infinity 等作为字符串发出会使这些字符串的语义不明确。它们需要像在 Python 和 GSON 实现中一样作为裸词发出。

【问题讨论】:

这正是replacement参数作业,没那么难。也许您可以详细说明您的实际问题,以及示例和示例数据? JSON.stringify(a:1,b:1/"gg", c:d:5, function(a,b,c)if(Object.is(NaN , b))return "NaN"; return b;) @dandavis 查看上面的更新。 如果你要否决这个问题,至少解释一下它有什么问题,以便我解决它。 如果您担心字符串冲突并希望使用快速的本机解析器,您可以使用 guid 代替,例如:"NaN"。 【参考方案1】:

这是一个例子

Javascript

var array1 = [-Infinity, -1, 0, 1, 2, NaN, 4, 5, Infinity],
    json = JSON.stringify(array1, function (key, value) 
        if (value !== value) 
            return 'NaN';
        

        if (value === Infinity) 
            return 'Infinity';
        

        if (value === -Infinity) 
            return '-Infinity';
        

        return value;
    ),
    array2 = JSON.parse(json, function (key, value) 
        if (value === 'NaN') 
            return NaN;
        

        if (value === 'Infinity') 
            return Infinity;
        

        if (value === '-Infinity') 
            return -Infinity;
        

        return value;
    );

console.log(json);
console.log(array2);

输出

["-Infinity",-1,0,1,2,"NaN",4,5,"Infinity"]
[-Infinity, -1, 0, 1, 2, NaN, 4, 5, Infinity]

参考文献

JSON.stringify

JSON.parse

开启jsFiddle

更新:

Javascript

var array1 = [-Infinity, -1, 0, 1, 2, NaN, 4, 5, Infinity],
    json = JSON.stringify(array1, function (key, value) 
        if (value !== value) 
            return '0/0';
        

        if (value === 1/0) 
            return '1/0';
        

        if (value === -1/0) 
            return '-1/0';
        

        return value;
    ),
    array2 = JSON.parse(json, function (key, value) 
        if (value === '0/0') 
            return 0/0;
        

        if (value === '1/0') 
            return Infinity;
        

        if (value === '-1/0') 
            return -1/0;
        

        return value;
    );

console.log(json);
console.log(array2);

输出

["-1/0",-1,0,1,2,"0/0",4,5,"1/0"]
[-Infinity, -1, 0, 1, 2, NaN, 4, 5, Infinity] 

开启jsFiddle

【讨论】:

见上面的更新 - 你使用的字符串的语义现在是模棱两可的。 他们好吗ambiguous?您没有向我们提供任何示例数据。我使用的示例仅是数字。因此,在这种情况下,这些字符串表示并不模棱两可,它们只表示那些特定的值。 如果你想要一个不符合规范的库,我建议你获取一份'JSON2' 并修改代码以满足你的需要。 或者,如果您担心的是字符串表示并想要替代方法,请尝试If you evaluate 1/0 you get Infinity, if you evaluate -1/0 you get -Infinity, if you evaluate 0/0 you get NaN. 因为,例如,字符串 Infinity 现在有两种可能的含义——字符串 Infinity 和无穷大的数字表示,接收者无法知道选择哪个含义。我无法提供代表所有可能发生的情况的示例数据 - 它几乎可以是任何对象。【参考方案2】:

JSON.stringifyreplacement 参数是非常适合这项工作的工具。

JSON.stringify(data, function(key, value) 
   if (value === Infinity) 
      return "Infinity";
    else if (value === -Infinity) 
      return "-Infinity";
    else if (value !== value) 
      return "NaN";
   
   return value;
);

另一方面,您可以使用JSON.parsereviver 参数。

 JSON.parse(data, function(key, value) 
   if (value === "Infinity") 
      return Infinity;
    else if (value === "-Infinity") 
      return -Infinity;
    else if (value === "NaN") 
      return NaN;
   
   return value;
);

【讨论】:

elses 之后不需要returns 查看上面的更新 - 此处的解决方案将歧义引入您选择表示 NaN 和 Inf 的字符串的语义中。 @Xotic750 我更喜欢else if,因为它可以缩短代码并且在这种情况下不会影响功能。不过感谢您的关注。 @elhefe 我同意,它们现在是模棱两可的,使用现有的本机实现我们无能为力。我明白了,你找到了解决方案,破解 JSON2 库。总帐

以上是关于强制 JSON.stringify() 发出这样做的 NaN / Infinity 或 JS JSON 库的主要内容,如果未能解决你的问题,请参考以下文章

IE 8 支持 JSON.stringify() 吗?

JSON.stringify 将 Infinity 转换为 null

JSON.stringify 将 Infinity 转换为 null

慎用 JSON.stringify

你不知道的冷知识:JSON.stringify 居然还能这样用?

JSON.stringify()还可以这么用