JSON.parse解析含转义双引号的JSON字符串触发语法错误排查
咱们先拆解一下你遇到的核心问题:你把JSON字符串包裹在JavaScript的单引号字符串中,导致JSON里的转义双引号被JS错误解析,直接破坏了JSON的语法结构。
具体原因说明
当PHP执行json_encode($this->Lang)时,会生成完全合法的JSON内容,比如其中的Header_Notification_Comment字段会是这样的:
"Header_Notification_Comment": "[A] commented on \"[O]\""
这里的\"是JSON规范要求的转义双引号,本身没有任何问题。
但你把这段JSON包裹在JS的单引号字符串里(var Lang = '...';)时,JavaScript的字符串解析规则会把\"直接转换成普通的"——因为在JS的单引号字符串中,\是转义字符,它会把后续的"转义成普通双引号(而非字符串的边界标记)。这就导致待解析的JSON变成了:
"Header_Notification_Comment": "[A] commented on "[O]""
此时字符串内部的"没有被转义,直接提前结束了JSON字符串,这就是JSON.parse抛出SyntaxError的根本原因。
另外你处理单引号的str_replace('\'', '\\\'', ...)其实是多余的:JSON规范中,字符串内部的单引号不需要转义,就算保留原有的',JSON.parse也能正确识别。
最优解决方案:直接输出为JS对象
其实完全不需要把JSON转成字符串再parse,json_encode生成的JSON本身就是合法的JavaScript对象字面量,直接赋值给JS变量即可:
echo '<script type="text/javascript">var Lang = '; echo json_encode($this->Lang); echo ';</script>';
这样生成的JS代码会直接是:
var Lang = {"Code":"en","Layout":"LtR",...};
JS可以直接使用Lang变量,没有任何转义问题,这是最简单也最可靠的做法。
备选方案:如果必须用字符串传递(不推荐)
如果你因为某些特殊需求,一定要把JSON放在字符串里再parse,那需要确保JS字符串里的所有转义字符都被正确保留——也就是把JSON中的\转成\\,让JS解析后依然保留\,这样JSON.parse才能识别转义:
$json = json_encode($this->Lang); // 先转义反斜杠,再转义单引号(避免破坏JS的单引号字符串边界) $json_escaped = str_replace(['\\', '\''], ['\\\\', '\\\''], $json); echo '<script type="text/javascript">var Lang = \'' . $json_escaped . '\'; Lang = JSON.parse(Lang);</script>';
这样生成的JS字符串里,原来的\"会变成\\",JS解析后得到\",JSON.parse就能正确识别这是转义的双引号了。
内容的提问来源于stack exchange,提问作者user8639775

