由于JSON中的单引号转义,jQuery.parseJSON抛出“无效的JSON”错误

我使用jQuery.post()向我的服务器发出请求,而我的服务器正在返回JSON对象(如{ "var": "value", ... } )。 但是,如果任何值包含单引号(正确转义像\' ),jQuery不能解析一个否则有效的JSON字符串。 以下是我的意思( 在Chrome的控制台中完成 )的示例:

 data = "{ \"status\": \"success\", \"newHtml\": \"Hello \\\'x\" }"; eval("x = " + data); // { newHtml: "Hello 'x", status: "success" } $.parseJSON(data); // Invalid JSON: { "status": "success", "newHtml": "Hello \'x" } 

这是正常的吗? 有没有办法通过JSON正确传递一个单引号?

根据JSON网站上的状态机图,只允许使用双引号字符,而不是单引号。 单引号字符不需要转义:

http://www.json.org/string.gif

更新 – 对于那些感兴趣的更多信息:


Douglas Crockford并没有具体说明为什么JSON规范不允许在字符串中使用单引号。 然而,在讨论JavaScript的附录E中的JSON时,他写道:

JSON的设计目标是最小的,可移植的,文本的和JavaScript的一个子集。 我们为了互操作而需要达成的协议越少,我们就越容易进行互操作。

所以也许他决定只允许使用双引号来定义字符串,因为这是所有JSON实现必须达成一致的一条规则。 因此,字符串中的单引号字符不可能意外终止字符串,因为根据定义,字符串只能由双引号字符终止。 因此,在形式说明中不需要转义单引号字符。


深入挖掘,Crockford的JSON for Java的org.json实现更加容许, 允许使用单引号字符:

toString方法生成的文本严格符合JSON语法规则。 建设者在他们将接受的文本中更宽容:

  • 字符串可能会被引用(单引号)。

这由JSONTokener源代码确认。 nextString方法接受转义的单引号字符,并将它们视为双引号字符:

 public String nextString(char quote) throws JSONException { char c; StringBuffer sb = new StringBuffer(); for (;;) { c = next(); switch (c) { ... case '\\': c = this.next(); switch (c) { ... case '"': case '\'': case '\\': case '/': sb.append(c); break; ... 

该方法的顶部是一个内容丰富的评论:

正式的JSON格式不允许单引号中的字符串,但允许实现接受它们。

所以有些实现会接受单引号 – 但是你不应该依赖这个。 许多流行的实现在这方面是相当严格的,并会拒绝包含单引号字符串和/或单引号的JSON。


最后,为了回到原来的问题, jQuery.parseJSON首先尝试使用浏览器的本机JSON解析器或加载的库(如json2.js)(如果适用的话)(注意jQuery逻辑基于的是JSON没有定义)。 因此,jQuery只能和底层实现一样宽容:

 parseJSON: function( data ) { ... // Attempt to parse using the native JSON parser first if ( window.JSON && window.JSON.parse ) { return window.JSON.parse( data ); } ... jQuery.error( "Invalid JSON: " + data ); }, 

据我所知,这些实现只遵守官方的JSON规范,不接受单引号,因此jQuery也没有。

如果你在一个字符串中需要一个单引号,由于\' \u0027规范定义,所以使用\u0027参见http://www.utf8-chartable.de/

编辑:请原谅我在评论中滥用“反引号”这个词。 我的意思是反斜杠 我的意思是,如果在其他字符串中嵌套了字符串,我认为使用unicode而不是大量反斜杠来转义单引号会更有用和更易读。 如果你没有嵌套,那么只要在那里放一个普通的旧报价就更简单了。

当您在查询中发送单引号时

 empid = " T'via" empid =escape(empid) 

当你得到包括单引号的价值

 var xxx = request.QueryString("empid") xxx= unscape(xxx) 

如果您想在查询中搜索/插入包含单引号的值xxx = Replace(empid,“'”,“''”)

我明白问题在哪里,当我看规格时,明确指出应该正确解析非转义的单引号。

我正在使用jQuery的jQuery.parseJSON函数来解析JSON字符串,但仍然得到解析错误,当用json_encode准备的数据中有一个单引号。

这可能是我的实现中的一个错误,看起来像这样(PHP – 服务器端):

 $data = array(); $elem = array(); $elem['name'] = 'Erik'; $elem['position'] = 'PHP Programmer'; $data[] = json_encode($elem); $elem = array(); $elem['name'] = 'Carl'; $elem['position'] = 'C Programmer'; $data[] = json_encode($elem); $jsonString = "[" . implode(", ", $data) . "]"; 

最后一步是我将JSON编码的字符串存储到JS变量中:

 <script type="text/javascript"> employees = jQuery.parseJSON('<?=$marker; ?>'); </script> 

如果我使用“”而不是“”,它仍然会抛出一个错误。

解:

唯一的工作是我使用位掩码JSON_HEX_APOS来转换单引号是这样的:

 json_encode($tmp, JSON_HEX_APOS); 

有解决这个问题的另一种方法吗? 我的代码是错的还是写得不好?

谢谢

使用CakePHP使用PHP的本地json_encode输出一个Javascript脚本块,引发类似的问题。 $ contractorCompanies包含具有单引号的值,正如上面所解释的,预期的json_encode($ contractorCompanies)不会因为其有效的JSON而转义它们。

 <?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".(json_encode($contractorCompanies)."' );"); ?> 

通过在JSON编码的字符串周围添加addslashes(),您可以避免引号,从而允许Cake / PHP将正确的javascript回传给浏览器。 JS错误消失。

 <?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".addslashes(json_encode($contractorCompanies))."' );"); ?> 

有趣。 你如何在服务器端生成你的JSON? 你是否使用了一个库函数(比如PHP中的json_encode ),还是用手建立了JSON字符串?

唯一引起我注意的是撇号( \' )。 看到你使用双引号,就像你的确应该那样,没有必要逃避单引号。 我不能检查是否确实是你的jQuery错误的原因,因为我还没有更新到版本1.4.1。

我试图将XHR请求中的JSON对象保存为HTML5数据属性。 我尝试了许多以上的解决方案,但没有成功。

我最终做的是用'代码'替换单引号&#39; 在stringify()方法之后使用正则表达式调用以下方法:

 var productToString = JSON.stringify(productObject); var quoteReplaced = productToString.replace(/'/g, "&#39;"); var anchor = '<a data-product=\'' + quoteReplaced + '\' href=\'#\'>' + productObject.name + '</a>'; // Here you can use the "anchor" variable to update your DOM element.