JSON 省略了 Infinity 和 NaN;ECMAScript 中的 JSON 状态?
Infinity
并且NaN
不是关键字或任何特殊的东西,它们只是全局对象上的属性(原样undefined
),因此可以更改。正是因为这个原因,JSON 没有将它们包含在规范中——本质上,任何真正的 JSON 字符串在 EcmaScript 中都应该有相同的结果,如果你这样做了eval(jsonString)
或JSON.parse(jsonString)
.
如果允许,那么有人可以注入类似于
NaN={valueOf:function(){ do evil }};
Infinity={valueOf:function(){ do evil }};
进入论坛(或其他),然后该站点上的任何 json 使用都可能受到损害。
关于原始问题:我同意用户“cbare”的观点,因为这是 JSON 中的一个不幸遗漏。IEEE754 将这些定义为浮点数的三个特殊值。所以 JSON 不能完全表示 IEEE754 浮点数。事实上,情况更糟,因为 ECMA262 5.1 中定义的 JSON 甚至没有定义其数字是否基于 IEEE754。由于为 ECMA262 中的 stringify() 函数描述的设计流程确实提到了三个特殊的 IEEE 值,因此可以怀疑其意图实际上是为了支持 IEEE754 浮点数。
作为另一个与问题无关的数据点:XML 数据类型 xs:float 和 xs:double 声明它们基于 IEEE754 浮点数,并且它们确实支持这三个特殊值的表示(请参阅 W3C XSD 1.0 第 2 部分, 数据类型)。
你能不能适应空对象模式,并在你的 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"、"-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"}"
如果您有权访问序列化代码,您可以将 Infinity 表示为 1.0e+1024。指数太大而无法用双精度表示,反序列化时表示为无穷大。适用于 webkit,不确定其他 json 解析器!