JSON.parse在有效的Json上失败。逃脱了控制角色。如果

时间:2015-01-18 10:50:20

标签: javascript jquery json

我已经转义了控制字符,并将我已验证的JSON提供给JSON.parse和jQuery.parseJSON。两者都给出了相同的结果。

收到错误消息"Unexpected token $"



$(function(){
    try{
        $.parseJSON('"\\\\\"$\\\\\"#,##0"');
    } catch (exception) {
        alert(exception.message);
    }    
});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
&#13;
&#13;
&#13;

感谢您查看此问题。

2 个答案:

答案 0 :(得分:5)

这里发生的事情是对字符串应用了两个级别的反斜杠删除。第一个是在浏览单引号字符串时由浏览器的JavaScript引擎完成的。在JavaScript中,单引号字符串和双引号字符串完全相同(除了单引号必须在单引号字符串中进行反斜杠转义且双引号必须< / em>在双引号字符串中反斜杠转义);两种类型的字符串都使用反斜杠转义码,例如\\用于反斜杠,\'用于单引号(冗余但在双引号字符串中接受),\"用于双引号(冗余)但在单引号字符串中接受。)

在JavaScript单引号字符串文字中,你有几个这类事件的实例,它们是有效的JSON双引号字符串:

"\\\\\"$\\\\\"#,##0"

浏览器解析后,该字符串包含以下字符(包括外部双引号,因为它们包含在单引号字符串中而未被删除):

"\\"$\\"#,##0"

你可以看到每一对连续的反斜杠都变成了单个字面反斜杠,两个奇数反斜杠后面跟一个双引号的情况都变成了文字的双引号。

是作为参数传递给$.parseJSON的文本,即第二级反斜杠删除时。在对上述文本进行JSON解析期间,前导双引号表示JSON字符串文字的开头,然后将该对反斜杠解释为单个文字反斜杠,然后紧跟在后面的双引号终止JSON字符串文字。后面的内容(美元,反斜杠,反斜杠等)是无效的JSON语法。

问题在于,您已经在JavaScript单引号字符串文字中嵌入了有效的JSON,虽然它恰好是fluke的有效JavaScript语法(但不会如果是JSON包含单引号,或者如果您尝试使用双引号来分隔JavaScript字符串文字),则在浏览器的JavaScript引擎解析后不再包含有效的JSON。

要解决此问题,您必须手动转义JSON内容以正确嵌入JavaScript字符串文字中,或者独立于JavaScript源加载它,例如,来自平面文件。

以下是使用最新示例代码解决问题的演示:

$(function() {
    try {
        alert($.parseJSON('{"key":"\\\\\\\\\\"$\\\\\\\\\\"#,##0"}').key); // works
        alert($.parseJSON('{"key":"\\\\\"$\\\\\"#,##0"}').key); // doesn't work
    } catch (exception) {
        alert(exception.message);
    }    
});

http://jsfiddle.net/814uw638/2/

由于JavaScript具有简单的转义方案(例如参见http://blogs.learnnowonline.com/2012/07/19/escape-sequences-in-string-literals-using-javascript/),因此在一般情况下解决此问题实际上非常容易。您只需要提前决定如何在JavaScript中引用字符串(单引号是一个好主意,因为JSON中的字符串总是双引号),然后在准备JavaScript源代码时,只需添加一个每个单引号前的反斜杠和嵌入式JSON中的每个反斜杠。这应该保证它完全有效,无论确切的JSON内容如何(当然,提供它是有效的JSON开头)。

答案 1 :(得分:3)

在你原来的问题中,为什么你需要首先做JSONparse呢?你可以轻松地通过

获得你想要的对象
var o = { blah }

通过手动删除大括号周围的单引号而不是

$.JSONparse('{blah}')

是否有任何理由首先评估字符串(即var s =&#39; {blah}&#39;然后执行$ .JSONparse(s))这是您原始代码的作用?不应该是必要的情况。既然你提到字符串是由JSON.stringify生成的,那么你就不应该将它显式地存储到一个变量中(即复制并粘贴它并在它周围加上引号)。

这里的主要问题是由JSON.stringify生成的字符串,该字符串已被正确转义,已经过评估&#39;一旦你手动将牙箍放在它周围。所以关键是要确保字符串没有得到评估&#39;

即使您想将字符串化变量传递给数据库或其他任何内容,也无需显式使用引号。一个人可以做到

var s = JSON.stringify(obj);
db.save("myobj",s)
var newObj = JSON.parse(db.load("myobj"))

字符串是逐字存储而不进行评估,因此当您检索字符串时,您将拥有完全相同的字符串。