知道为什么JSON省略了NaN和+/- Infinity吗?它将Javascript置于一种奇怪的情况中,如果对象包含NaN或+/-无穷大值,则对象将不可序列化。

看起来这已经是铁板一块了:参见RFC4627和ECMA-262(第24.5.2节,JSON。ECMA-262 pdf最后一次编辑第683页):

有限数字被字符串化,就像调用ToString(number)一样。NaN和Infinity,无论符号是什么,都表示为字符串null。


当前回答

{"key":Infinity}等情况的潜在解决方案:

JSON.parse(theString.replace(/":(Infinity|-IsNaN)/g, '":"{{$1}}"'), function(k, v) {
   if (v === '{{Infinity}}') return Infinity;
   else if (v === '{{-Infinity}}') return -Infinity;
   else if (v === '{{NaN}}') return NaN;
   return v;
   });

一般思想是用解析时可以识别的字符串替换出现的无效值,然后用适当的JavaScript表示替换回来。

其他回答

Infinity和NaN不是关键字或任何特殊的东西,它们只是全局对象上的属性(未定义),因此可以更改。正是因为这个原因,JSON没有在规范中包含它们——本质上,如果你使用eval(jsonString)或JSON.parse(jsonString),任何真正的JSON字符串在EcmaScript中都应该有相同的结果。

如果允许,那么有人可以注入类似于

NaN={valueOf:function(){ do evil }};
Infinity={valueOf:function(){ do evil }};

进入一个论坛(或任何地方),然后该网站上的任何json使用都可能受到损害。

如果您可以访问序列化代码,则可以将Infinity表示为1.0e+1024。指数太大,不能用双精度表示,反序列化时,它表示为无穷大。适用于webkit,不确定其他json解析器!

JSON5允许使用标准的Javascript符号来表示正无穷大和负无穷大、NaN以及许多其他在JSON中被省略的有效ECMAScript(后面的逗号等)。

https://json5.org/

这使得JSON成为一种更有用的格式。

然而,无论是使用JSON还是JSON5:出于安全原因,总是总是解析——不要计算!!

如果你像我一样无法控制序列化代码,你可以用null或任何其他值来处理NaN值,如下所示:

$.get("file.json", theCallback)
.fail(function(data) {
  theCallback(JSON.parse(data.responseText.replace(/NaN/g,'null'))); 
} );

本质上,当原始json解析器检测到无效令牌时,.fail将被调用。然后使用字符串replace替换无效的令牌。在我的情况下,它是一个例外的序列化器返回NaN值,所以这个方法是最好的方法。如果结果通常包含无效令牌,最好不要使用$。而不是手动检索JSON结果,并始终运行字符串替换。

字符串“Infinity”、“-Infinity”和“NaN”都被强制转换为JS中的期望值。所以我认为在JSON中表示这些值的正确方法是字符串。

> +"Infinity"
Infinity

> +"-Infinity"
-Infinity

> +"NaN"
NaN

JSON太可惜了。Stringify默认情况下不这样做。但有一个办法:

> JSON.stringify({ x: Infinity }, function (k,v) { return v === Infinity ? "Infinity" : v; })
"{"x":"Infinity"}"