知道为什么JSON省略了NaN和+/- Infinity吗?它将Javascript置于一种奇怪的情况中,如果对象包含NaN或+/-无穷大值,则对象将不可序列化。
看起来这已经是铁板一块了:参见RFC4627和ECMA-262(第24.5.2节,JSON。ECMA-262 pdf最后一次编辑第683页):
有限数字被字符串化,就像调用ToString(number)一样。NaN和Infinity,无论符号是什么,都表示为字符串null。
知道为什么JSON省略了NaN和+/- Infinity吗?它将Javascript置于一种奇怪的情况中,如果对象包含NaN或+/-无穷大值,则对象将不可序列化。
看起来这已经是铁板一块了:参见RFC4627和ECMA-262(第24.5.2节,JSON。ECMA-262 pdf最后一次编辑第683页):
有限数字被字符串化,就像调用ToString(number)一样。NaN和Infinity,无论符号是什么,都表示为字符串null。
当前回答
当前的IEEE Std 754-2008包含了两种不同的64位浮点表示形式的定义:十进制64位浮点类型和二进制64位浮点类型。
在舍入字符串后,.99999990000000006与IEEE二进制64位表示中的.9999999相同,但与IEEE十进制64位表示中的.9999999不同。在64位IEEE十进制浮点数中,.99999990000000006舍入为值.9999999000000001,这与十进制值.9999999不相同。
由于JSON只是将数值视为十进制数字的数字字符串,因此同时支持IEEE二进制和十进制浮点表示的系统(如IBM Power)无法确定两个可能的IEEE数字浮点值中的哪一个是要使用的。
其他回答
{"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表示替换回来。
如果你像我一样无法控制序列化代码,你可以用null或任何其他值来处理NaN值,如下所示:
$.get("file.json", theCallback)
.fail(function(data) {
theCallback(JSON.parse(data.responseText.replace(/NaN/g,'null')));
} );
本质上,当原始json解析器检测到无效令牌时,.fail将被调用。然后使用字符串replace替换无效的令牌。在我的情况下,它是一个例外的序列化器返回NaN值,所以这个方法是最好的方法。如果结果通常包含无效令牌,最好不要使用$。而不是手动检索JSON结果,并始终运行字符串替换。
当前的IEEE Std 754-2008包含了两种不同的64位浮点表示形式的定义:十进制64位浮点类型和二进制64位浮点类型。
在舍入字符串后,.99999990000000006与IEEE二进制64位表示中的.9999999相同,但与IEEE十进制64位表示中的.9999999不同。在64位IEEE十进制浮点数中,.99999990000000006舍入为值.9999999000000001,这与十进制值.9999999不相同。
由于JSON只是将数值视为十进制数字的数字字符串,因此同时支持IEEE二进制和十进制浮点表示的系统(如IBM Power)无法确定两个可能的IEEE数字浮点值中的哪一个是要使用的。
你能适应空对象模式,并在JSON中表示这样的值吗
"myNum" : {
"isNaN" :false,
"isInfinity" :true
}
然后在检查时,可以检查类型
if (typeof(myObj.myNum) == 'number') {/* do this */}
else if (myObj.myNum.isNaN) {/* do that*/}
else if (myObj.myNum.isInfinity) {/* Do another thing */}
我知道在Java中,你可以重写序列化方法来实现这样的事情。不确定你的序列化从哪里来,所以我不能详细说明如何在序列化方法中实现它。
Infinity和NaN不是关键字或任何特殊的东西,它们只是全局对象上的属性(未定义),因此可以更改。正是因为这个原因,JSON没有在规范中包含它们——本质上,如果你使用eval(jsonString)或JSON.parse(jsonString),任何真正的JSON字符串在EcmaScript中都应该有相同的结果。
如果允许,那么有人可以注入类似于
NaN={valueOf:function(){ do evil }};
Infinity={valueOf:function(){ do evil }};
进入一个论坛(或任何地方),然后该网站上的任何json使用都可能受到损害。