gson 如何解析Node.js中包含“NaN”的JSON字符串

yuvru6vn  于 2022-11-06  发布在  Node.js
关注(0)|答案(5)|浏览(255)

有一个node.js应用程序,该应用程序接收包含文字NaN的JSON数据字符串,例如

"[1, 2, 3, NaN, 5, 6]"

这会导致Node.js中的JSON.parse(...)崩溃。如果可以的话,我想将其解析为一个对象。
我知道NaN不是JSON规范的一部分。大多数SO链接(sending NaN in json)建议修复输出。
在这里,虽然数据是在一个我不控制的服务器上产生的,但它是由一个商业Java库产生的,我可以在那里看到源代码,而且它是由Google的Gson库产生的:

private Gson gson = (new GsonBuilder().serializeSpecialFloatingPointValues().create()); 
... 
gson.toJson(data[i], Vector.class, jsonOut)

所以这看起来像是一个合法的源代码。根据Gson API Javadoc,它说我应该能够解析它:
JSON规范的第2.4节不允许特殊的双精度值(NaN,无穷大,-无穷大)。然而,Javascript规范(见4.3.20、4.3.22、4.3.23节)允许这些值作为有效的Javascript值。而且,大多数JavaScript引擎将毫无问题地接受JSON中的这些特殊值。因此,在实际层面上,即使JSON规范不允许使用这些值,也应该将它们作为有效的JSON来接受。
尽管如此,这在Node.js和Chrome中都失败了:JSON.parse('[1,2,3,NaN,"5"]')

在JSON.parse()中是否设置了标志?或者是否有一个替代的解析器接受NaN作为文字?

我已经在谷歌上搜索了一段时间,但似乎找不到一个关于这个问题的医生。
PHP:如何将无穷大或NaN数字编码为JSON?

tyu7yeag

tyu7yeag1#

有一个node.js应用程序,该应用程序接收包含文字NaN的JSON数据字符串,例如
那么你的NodeJS应用不是在接收JSON,而是在接收类似JSON的文本。NaN不是一个有效的JSON令牌。
三个选项:

1.获取源代码以正确生成JSON

这显然是首选的方法。数据不是JSON,应该被修复,这将修复您的问题。

2.以简单的方式容忍NaN

您可以在解析它之前将其替换为null,例如:

var result = JSON.parse(yourString.replace(/\bNaN\b/g, "null"));

......然后在结果中处理null。但这是非常简单的,它不允许字符NaN出现在字符串的某个地方。
或者,旋转Matt Ball的reviver idea (现已删除),您可以将其更改为一个特殊字符串(如"***NaN***"),然后使用reviver将其替换为真实的的NaN

var result = JSON.parse(yourString.replace(/\bNaN\b/g, '"***NaN***"'), function(key, value) {
    return value === "***NaN***" ? NaN : value;
});

......但这也有同样的问题,即思想有点简单,假设字符NaN从未出现在适当的位置。

3.使用 (颤抖!)eval

如果您知道并信任此数据的来源,并且数据在传输过程中不可能被篡改,则可以使用eval而不是JSON.parse来解析数据。由于eval支持完整的JavaScript语法,包括NaN,这是可行的。希望我的警告足够大胆,让人们明白我只会在非常,非常,* 非常 * 的情况下推荐这一点。但再次,记住eval允许任意执行代码,所以如果字符串有任何被篡改的可能性,不要使用它。

v1l68za4

v1l68za42#

当你处理任何数学或工业数据时,NaN非常方便(无穷大也是如此),它是自IEEE754以来的一个工业标准。
显然,这就是为什么有些库,特别是GSON,允许您将它们包含在它们生成的JSON中,从而失去了标准的纯粹性并获得了合理性。
当您交换复杂的动态对象时,Revival和regex解决方案在真实的项目中不能可靠地使用。
eval也有问题,其中之一是当JSON字符串很大时,它在IE上很容易崩溃,另一个问题是安全风险。
这就是为什么我写了一个特定的解析器(用于生产):JSON.parseMore

iyr7buue

iyr7buue3#

你可以使用JSON5.library.a从工程页面中引用:
JSON5数据交换格式(英语:JSON5 Data Interchange Format,缩写为JSON5)是JSON的一个超集,其目的是通过扩展JSON的语法以包含ECMAScript 5.1的一些结果来减轻JSON的一些限制。
这个JavaScript库是JSON5解析和序列化库的官方参考实现。
正如你所期望的,它确实支持解析NaN(与Python等序列化它们的方式兼容):

JSON5.parse("[1, 2, 3, NaN, 5, 6]")
> (6) [1, 2, 3, NaN, 5, 6]
7gs2gvoe

7gs2gvoe4#

正确的解决方案是重新编译解析器,并为源代码库提供一个“allowNan”布尔标志,这是其他库的解决方案(python的解决方案)。
好的JSON库可以通过设置正确的标志来解析几乎任何与JSON有点相似的内容(perl的JSON.pm非常灵活)...但是在编写消息时,它们会生成标准的JSON。
IE:让房间比你发现的时候更干净。

zfycwa2u

zfycwa2u5#

只是一个小补充TJ克劳德的已经足够全面的答复,我宁愿使用

var result = JSON.parse(yourString.replace(/\bNaN\b/g, '"NaN"'));

因为我实际上需要知道它是否是NaN值。
我也会在fetch或axios GET请求中这样做,只有在默认JSON解析失败并且数据以字符串形式出现时。

const StringConstructor = "".constructor;

if (data.constructor === StringConstructor) {
    data = JSON.parse(tableData.data.replace(/\bNaN\b/g, '"NaN"'))
}

相关问题