JSON忽略了Infinity和NaN;ECMAScript中的JSON状态?

2020/10/21 13:41 · javascript ·  · 0评论

知道为什么JSON遗漏了NaN和+/- Infinity吗?如果它们包含NaN或+/-无限值,则Javascript处于一种奇怪的情况下,否则本来可以序列化的对象就不会被序列化。

看起来像是一成不变的:请参阅RFC4627ECMA-262(第24.5.2节,JSON.stringify,注意4,最后编辑的ECMA-262 pdf第683页):

有限数字被字符串化,好像通过调用ToString(number)NaN和Infinity(不考虑符号)均表示为String null

Infinity并且NaN不是关键字或任何特殊内容,它们只是全局对象上的属性(按原样undefined),因此可以更改。因此,JSON不在规范中包含它们-本质上,如果您使用eval(jsonString)或,则任何真正的JSON字符串在EcmaScript中的结果都应相同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解析器!

对于诸如{“ 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表示形式将其替换回来。

原因在标准ECMA-404第1版JSON数据交换语法的第ii页中说明

JSON与数字无关。在任何编程语言中,可以有各种容量和补码形式的数字类型,固定或浮动,二进制或十进制。这会使不同编程语言之间的交换变得困难。JSON而是仅提供人类使用的数字表示形式:数字序列。所有编程语言都知道如何理解数字序列,即使它们在内部表示形式上存在分歧。这足以允许互换。

正如许多人所声称的,原因并不是由于NaNInfinityECMA脚本的表示简单性是JSON的核心设计原则。

因为它是如此简单,所以JSON语法不会发生变化。作为基础符号,这给了JSON以极大的稳定性

当前的IEEE Std 754-2008包含两种不同的64位浮点表示形式的定义:十进制64位浮点类型和二进制64位浮点类型。

舍入后的字符串.99999990000000006相同.9999999的IEEE二进制64位表示,但它是一样的.9999999在IEEE十进制的64位表示。在64位IEEE中,十进制浮点数.99999990000000006舍入.9999999000000001为与十进制.9999999值不同的值。

由于JSON仅将数字值视为十进制数字字符串,因此无法同时支持IEEE二进制和十进制浮点表示形式的系统(例如IBM Power)来确定两个可能的IEEE数字浮点值中的哪一个是预期的。

如果像我一样无法控制序列化代码,则可以通过将NaN值替换为null或任何其他值来处理NaN值,如下所示:

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

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

本文地址:http://javascript.askforanswer.com/jsonhulueleinfinityhenanecmascriptzhongdejsonzhuangtai.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!