小编典典

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

all

我正在使用我的服务器向我的服务器发出请求,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 正确传递单引号?


阅读 101

收藏
2022-06-30

共1个答案

小编典典

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

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

更新 - 为感兴趣的人提供更多信息:


Douglas Crockford 没有具体说明为什么 JSON 规范不允许在字符串中转义单引号。然而,在他在JavaScript: The Good
Parts 的附录 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 也不接受。

2022-06-30