当涉及转义字符时,Javascript eval无法评估json

时间:2015-08-05 07:12:38

标签: javascript json eval rhino

我正在使用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",&#34 ;日期":" 2015-12-31T00:00:00"" TextValue":" {\"标识\":\ " 1 \" \"名称\":\"多尔蒂\" \"联系人姓名\":\&# 34; May C \",\" ContactEmail \":\" may.c@gamil.com \",\" Total \&#34 ;:25,\"电话\":\" 111-111-1111 \" \"类型\":\"日\" \"注\":[{\"评论\":\"一个\" \"日期\":\" 2014-11-27T00:00:00.000 \"},{\"评论\":\"两个\&#34 ; \"日期\":\" 2014-11-28T00:00:00.000 \"}],\" ImportComplete \":真, \" RunComplete \":真,\" CompleteDate \":\" 2014-07-31T00:00:00.000 \" \&#34 ;金额\":2400.00,\" ProcessingComplete \":真}"" NumberValue":4444.5555,"则DateValue":& #34; 2014-12-01T00:00:00"}&#39 ;;

var find =' \"';

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

var inj = json.replace(正则表达式,'"');

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

1 个答案:

答案 0 :(得分:0)

令人困惑的反斜杠

你遇到的问题是由于没有完全理解转义字符这一事实,当你有多个“字符串”深度时。虽然单个斜杠对于一个级别是好的,但是:

"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引擎使用一级转义,但仍然在字符串中保留另一级别。 e.g。

'"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."';
  

忽略我的随机Douglas Adams引号被分成多行(使用+),我只是为了便于在固定宽度区域内阅读而这样做。我保持它可以通过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系统可以避免这种情况。