当数据包含连续问号时,jQuery $.ajax()无法理解的行为

Uncomprehensible jQuery $.ajax() behavior when data contains consecutive question marks

本文关键字:ajax 连续 数据包 jQuery      更新时间:2023-09-26

我希望这足够清楚,我花了很多时间试图确定这个问题,所以我可能没有多少时间来写一个完美的问题。此外,这可能不得不进入jQuery bug报告,但我宁愿先在这里发布,因为我是一个相对的JavaScript新手,所以也许我做错了什么…

我创建了下面一段代码来复制它。它使用PHP将接收到的数据回显到浏览器,尽管它可以在没有PHP的情况下工作。

这个问题在Firefox 4和Chrome 10中也会出现。您需要控制台来查看发生了什么。

代码如下:

<?
$input = file_get_contents('php://input');
if (isset($input) and !empty($input)) {
    echo $input;
    die();
}
?>
<html>
    <head>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
        <script>
            $(function(){
                var jsonData = {
                    "something":"??"
                };
                jsonData = JSON.stringify(jsonData);
                var onSuccess = function(data){
                    console.log("Ajax Success!");
                    console.log(data);
                }
                var onError = function(jqXHR, textStatus, errorThrown){
                    console.log("Ajax Error: "+textStatus);
                    console.log("More info:");
                    console.log(errorThrown);           
                    console.log(jqXHR);         
                }
                console.log("Now sending this: "+jsonData+" through Ajax...");
                var ajaxCmd = {
                    "url"       : "test.php", 
                    "dataType": "json",
                    "type"  : "POST",
                    "async" : false,
                    "error"     : onError,
                    "success"   : onSuccess,
                    "data"  : jsonData
                };
                $.ajax(ajaxCmd);
            });
        </script>
    </head>
    <body>
        <pre>Check your JavaScript console...</pre>
    </body>
</html>
当加载

时,它抛出一些明显无关的解析错误或异常(取决于浏览器)。应该发送的json是{"something":"??}但是如果你在Firebug(或Chrome等效)的网络选项卡中检查它,你会看到"?? ?"被一些jQuery字符串取代,看起来像:jQuery152026845051744021475_1303152126170

这就是服务器接收到的。

此问题仅发生在发送的JSON对象内的值字段中有两个或多个连续问号时,即使那里有其他字母。加上一个问号,似乎行得通。另外,将"dataType"更改为"text"可以修复此问题。但是我需要所有这些功能!

如果你注释掉"jsonData = JSON.stringify(jsonData);"或"$.ajax(ajaxCmd);",错误也会奇迹般地消失。

更多信息:

Chrome控制台输出:

test.php:21Now sending this: {"something":"??"} through Ajax...
jquery.min.js:16Uncaught SyntaxError: Unexpected token :
test.php:16Ajax Error: parsererror
test.php:17More info:
test.php:18jQuery15206220591682940722_1303153398797 was not called
test.php:19
Object

Firebug输出:

Now sending this: {"something":"??"} through Ajax...
Ajax Error: parsererror
More info:
jQuery15206494160738701454_1303153492631 was not called
Object { readyState=4, responseText="{"something":"jQuery152...8701454_1303153492631"}", more...}
invalid label
{"something":"jQuery15206494160738701454_1303153492631"}

jQuery在使用jsonp时使用??作为回调函数的占位符。当它解析Ajax请求并发现双问号(或更多问号)时,它会自动假定您正在尝试使用jsonp。当您手动设置内容类型时,它将忽略问号。

因此,使用contentType: 来避免这个问题
$.ajax(
    url: "your-url.php",
    dataType: "json",                 // what you expect the server to return
    contentType: "application/json",  // what you are sending
    ...
);
参考:

jQuery Bugtracker: $。Ajax更改了帖子内容,如果包含"?? ?"(2问号)

如果不打算将"data"值格式化为有效的HTML查询字符串,则不应该对其进行预字符串化。正如您所注意到的,如果不调用"JSON.stringify()",则它可以工作。这是因为库已经知道如何为你处理。

现在,如果你想将JSON字符串作为参数本身发送到期望解码JSON的服务器端代码,那么你需要将其设置为参数:

    $.ajax(url, {
      // ...
      data: { jsonParam: jsonData },
      // ...
    });

现在,您的服务器将看到一个HTTP请求,其参数名为"jsonParam",其值将是json字符串化的字符串。

我认为你正在寻找的答案是在AJAX调用选项中设置jsonp:false。我也遇到过同样的问题,并通过这样做解决了它。

阅读这个类似问题的答案了解更多细节:从jQuery 1.4升级到1.5后,Post数据被覆盖

因为现有的答案都没有提到这一点。您可以通过添加

来解决这个问题。
jsonp: false

我在1.5.2中遇到了这样的问题。这是jQuery的bug: http://bugs.jquery.com/ticket/8417。你可以更新到1.6.4或者这样做:jQuery函数"jQuery. ajaxprefilter "改变:

var dataIsString = ( typeof s.data === "string" );

var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
        ( typeof s.data === "string" );

并将该变量更改为下面的"if"条件:

if ( s.dataTypes[ 0 ] === "jsonp" ||
        originalSettings.jsonpCallback ||
        originalSettings.jsonp != null ||
        s.jsonp !== false && ( jsre.test( s.url ) ||
                dataIsString && jsre.test( s.data ) ) ) {
                inspectData && jsre.test( s.data ) ) ) {

与jQuery 1.71完全相同的问题,双问号和一些疯狂的字符串被插入。

可以通过删除

来修复它
dataType: 'JSON'

,然后它神奇地停止了。

这听起来像是编码问题。如果您的数据不是UTF-8格式(如MS Word或其他),则可能发生这种情况。

我也遇到了同样的问题。用encodeURIComponent转义值完成了这项工作!

我也面临同样的问题。指定"contentType":"application/json;Charset =utf-8"解决了这个问题。

jQuery.ajax({
    "url": url,
    "data": JSON.stringify(payload),
    "type": "POST",
    "dataType": "json",
    "contentType":"application/json; charset=utf-8",
    "success": function(data) {
    },
    "error": function(jqXHR, textStatus, errorThrown) {
    }
});