【问题标题】:Javascript eval fails to evaluate json when escape characters are involved当涉及转义字符时,Javascript eval 无法评估 json
【发布时间】:2023-12-20 04:49:01
【问题描述】:

我正在使用 rhino javascript 引擎来评估 json。 Json结构如下:

{"DataName":"111","Id":"222","Date":"2015-12-31T00:00:00","TextValue":"{\"Id\":\"1\",\"Name\":\"Daugherty\",\"ContactName\":\"May C\",\"ContactEmail\":\"may.c@gamil.com\",\"Total\":25,\"Phone\":\"111-111-1111\",\"Type\":\"Daily\",\"Notes\":[{\"Comments\":\"One\",\"Date\":\"2014-11-27T00:00:00.000\"},{\"Comments\":\"Two\",\"Date\":\"2014-11-28T00:00:00.000\"}],\"ImportComplete\":true,\"RunComplete\":true,\"CompleteDate\":\"2014-07-31T00:00:00.000\",\"Amount\":2400.00,\"ProcessingComplete\":true}","NumberValue":4444.5555,"DateValue":"2014-12-01T00:00:00"}

由于我使用的是 Rhino js 引擎,我不能使用 JSON.parse 和 JSON.stringify。 正如您所看到的,json 嵌入了 json,这个 json 我是从一个 .net web api 获得的,它放置了转义字符“\”。我正在尝试替换 javascript 中的转义字符,但没有帮助。

在 javascript 中有什么方法可以替换转义字符并使用“eval()”来评估 json。

这是我正在尝试的代码

var json = '{"DataName":"111","Id":"222","Date":"2015-12-31T00:00:00","TextValue":"{\"Id\ ":\"1\",\"姓名\":\"Daugherty\",\"ContactName\":\"May C\",\"ContactEmail\":\"may.c@gamil.com\" ,\"Total\":25,\"Phone\":\"111-111-1111\",\"Type\":\"Daily\",\"Notes\":[{\"Comments\" :\"一个\",\"日期\":\"2014-11-27T00:00:00.000\"},{\"评论\":\"两个\",\"日期\":\"2014 -11-28T00:00:00.000\"}],\"ImportComplete\":true,\"RunComplete\":true,\"CompleteDate\":\"2014-07-31T00:00:00.000\",\ "金额\":2400.00,\"ProcessingComplete\":true}","NumberValue":4444.5555,"DateValue":"2014-12-01T00:00:00"}';

var find = '\"';

var regex = new RegExp(find,'g');

var inj = json.replace(regex,'"');

var pl = eval('(' + inj +')');

【问题讨论】:

  • 为什么要这样做?为什么不在外部 JSON 上使用JSON.parse(),然后在内部 JSON 上再次使用它?不需要eval 或替换转义字符...有吗?
  • 所以你可以使用JSON.parse,但是你选择使用eval?
  • 你可以JSON.parse整个字符串,然后一旦它是一个对象,你就可以解析较小的。
  • 我的错,我已经编辑了帖子。我不能使用 JSON.parse 方法。
  • @RushikeshR:为什么不呢?你用的什么版本的 Rhino 不支持JSON.parse

标签: javascript json eval rhino


【解决方案1】:

令人困惑的反斜杠

您遇到的问题是由于没有完全理解转义字符,当您的“字符串”深度超过一层时。虽然单个斜线适用于一个级别,即:

"It is no coincidence that in no known language does the " + 
"phrase \"As pretty as an Airport\" appear.";

如果你接受它,然后用外引号括起来:

'"It is no coincidence that in no known language does the "' + 
'"phrase \"As pretty as an Airport\" appear."';

反斜杠(如果解析字符串的系统支持作为转义字符)适用于最外层的包装引号,而不是以前的任何内部引号/字符串。这意味着一旦 js 引擎解析了字符串,内部的字符串就会是。

'"It is no coincidence that in no known language does the phrase "As pretty as an Airport" appear."';

这使得无法从原始字符串中区分"\"。为了解决这个问题,您需要在包装之前转义原始字符串中的反斜杠。这导致 JavaScript 引擎使用了一级转义,但仍然在字符串中保留了另一级。例如

'"It is no coincidence that in no known language does the "' + 
'"phrase \\"As pretty as an Airport\\" appear."';

现在当字符串被解析时,在内部它将是:

'"It is no coincidence that in no known language does the phrase \"As pretty as an Airport\" appear."';

忽略我的随机道格拉斯亚当斯报价被分隔成多行(使用+),我这样做只是为了便于在固定宽度区域内阅读。我让它可以被 JavaScript 解析,以防万一人们复制和粘贴并期望事情能正常工作。

因此,为了解决您的问题,您的 JSON 源代码(在放入 JavaScript 代码之前)必须如下所示:

var json = '{"DataName":"111","Id":"222","Date":"2015-12-31T00:00:00","TextValue":"{\\"Id\\":\\"1\\",\\"Name\\":\\"Daugherty\\",\\"ContactName\\":\\"May C\\",\\"ContactEmail\\":\\"may.c@gamil.com\\",\\"Total\\":25,\\"Phone\\":\\"111-111-1111\\",\\"Type\\":\\"Daily\\",\\"Notes\\":[{\\"Comments\\":\\"One\\",\\"Date\\":\\"2014-11-27T00:00:00.000\\"},{\\"Comments\\":\\"Two\\",\\"Date\\":\\"2014-11-28T00:00:00.000\\"}],\\"ImportComplete\\":true,\\"RunComplete\\":true,\\"CompleteDate\\":\\"2014-07-31T00:00:00.000\\",\\"Amount\\":2400.00,\\"ProcessingComplete\\":true}","NumberValue":4444.5555,"DateValue":"2014-12-01T00:00:00"}';

你应该直接找到上面的eval,没有任何替换。

为了以编程方式实现上述目标,您必须查看您使用的 .NET 系统以转义反斜杠的方式提供了什么。我主要在服务器端使用 PHP 或 Python。使用您可以使用的那些语言:

为简洁起见,下面的 $ss 字符串已被裁剪。

<?php
$s = '{"DataName":"111","Id":"222"...';
$s = str_replace("\\", "\\\\", $s);
echo "var json = '$s';";

或者...

#!/usr/bin/env python
s = r'{"DataName":"111","Id":"222"...'
s = s.replace("\\", "\\\\")
print "var json = '" + s + "';"


另一种解决方案

这完全取决于您如何请求在 JavaScript 中包装在字符串中的内容。如果您有能力从服务器端写出您的 js(很可能使用 .NET)。就像我在上面展示的 PHP 或 Python 一样,您根本不需要将内容包装在字符串中。相反,您可以只输出内容而不用单引号括起来。然后 JavaScript 将只解析并将其视为文字对象结构:

var jso = {"DataName":"111","Id":"222","Date":"2015-12-31T00:00:00","TextValue":"{\"Id\":\"1\",\"Name\":\"Daugherty\",\"ContactName\":\"May C\",\"ContactEmail\":\"may.c@gamil.com\",\"Total\":25,\"Phone\":\"111-111-1111\",\"Type\":\"Daily\",\"Notes\":[{\"Comments\":\"One\",\"Date\":\"2014-11-27T00:00:00.000\"},{\"Comments\":\"Two\",\"Date\":\"2014-11-28T00:00:00.000\"}],\"ImportComplete\":true,\"RunComplete\":true,\"CompleteDate\":\"2014-07-31T00:00:00.000\",\"Amount\":2400.00,\"ProcessingComplete\":true}","NumberValue":4444.5555,"DateValue":"2014-12-01T00:00:00"};

这是可行的,因为 JSON 只是 JavaScript 对象的更严格版本,您已经拥有的引用/转义级别可以正常工作。

上述解决方案的唯一缺点是您必须隐含地信任您从中获取这些数据的来源,并且它必须始终保持良好的格式。如果没有,您可能会在代码中引入解析错误或不需要的 js; eval/JSON.parse 系统可以避免这种情况。

【讨论】:

    最近更新 更多