使用jsonp内容类型的jQuery.ajax请求后出现解析错误

60

我正在使用 jQuery 版本 1.5.1 来执行以下的 Ajax 调用:

$.ajax({
    dataType: 'jsonp',
    data: { api_key : apiKey },
    url: "http://de.dawanda.com/api/v1/" + resource + ".json",
    success: function(data) { console.log(data); },
    error: function(jqXHR, textStatus, errorThrown) { console.log(errorThrown); console.log(textStatus); }
});

服务器会用一个有效的JSON对象作为响应返回:

{
  "response": {
    "type":"category",
    "entries":1,
    "params":{
      "format":"json",
      "api_key":"c9f11509529b219766a3d301d9c988ae9f6f67fb",
      "id":"406",
      "callback":"jQuery15109935275333671539_1300495251986",
      "_":"1300495252693"
    },
    "pages":1,
    "result":{
      "category":{
        "product_count":0,
        "id":406,
        "restful_path":"/categories/406",
        "parent_id":null,
        "name":"Oberteile"
       }
     }
   }
 }

但成功回调从未被调用,相反,错误回调会产生以下输出:

jQuery15109935275333671539_1300495251986 was not called
parsererror

这是为什么呢?

我在使用jQuery时没有使用其他额外的库。

编辑:

如果我尝试使用"dataTypes"中的"json"来进行ajax调用,服务器会以空字符串响应。

9个回答

60

JSONP要求响应被包裹在某种回调函数中,因为它通过将脚本标记注入文档作为从另一个域加载数据的机制来工作。

基本上,发生的事情是一个脚本标记会像这样动态地插入到文档中:

<script src="http://the.other.server.com/foo?callback=someFn"></script>

回调函数取决于你调用的资源,通常参数名为callback

然后使用someFn来处理服务器返回的数据,所以服务器应该响应:

someFn({theData: 'here'});

someFn作为请求的一部分进行传递,因此服务器需要读取它并适当地包装数据。

这一切都假设您正在从另一个域中获取内容。如果是这样,您将受到同源策略的限制:http://en.wikipedia.org/wiki/Same_origin_policy


3
问题中的API是供应商提供的公共API,它仅限制调用为jsonp。 Jsonp调用将得到响应,但作为普通JSON对象返回。 - Thomas
8
在这个例子中,someFn是回调函数,服务器应该以以下方式响应:jQuery15109935275333671539_1300495251986({...}); - Adam Morris
3
谢天谢地,但愿他们能加上一些该死的文档。 - Kevin
3
我不理解这一点。你的意思是我需要用例如 $callBack({$myJsonResult}); 来包装来自服务器的响应吗?我需要在服务器端完成这个过程吗? - PinoyStackOverflower
1
@AdamMorris 服务器怎么知道这个函数的存在?我的意思是 jQuery15109935275333671539_1300495251986 这个长数字是什么?你怎么把这个信息传递给服务器? - stallingOne
这个方法完全解决了我的解析错误问题。 - Hasanuzzaman Sattar

10

在升级到Jquery 1.5并尝试跨域调用后,我遇到了同样的问题。最终我发现使用$.getJSON可以解决问题。具体来说:

$.getJSON(url,
    function(data){
        yourFunction(data);
       return false;
    });

我使用的URL是这样的:

var url = WEB_SERVER_URL;
url = url + "&a=" + lat;
url = url + "&b=" + lng; ....
url = url + "&jsoncallback=?";

在另一台我有控制权的服务器上运行的服务器中,添加了以下代码:

PrintWriter writer = response.getWriter();
String jsonString = json.toString(JSON_SPACING);
String callback = request.getParameter("jsoncallback");
// if callback in URL and is not just the "?" (e.g. from localhost)
if (callback != null && callback.length() > 1)
{
    writer.write(callback + "(" + jsonString + ");");
}
else
{
    writer.write(jsonString);
}

(json对象是JSONObject的实例,代码可以在这里找到:http://www.json.org/java/


6
当您使用jsonp作为数据类型(进行跨域请求)时,Jquery会生成随机函数并将其附加到请求的url中作为名为callback的查询字符串(callback =?),您需要将响应json数据附加为该函数的参数,如下所示 -
url : http://www.dotnetbull.com/cross-domain-call.ashx?ref=jquery-jsonp-request
url call by ajax :
http://www.dotnetbull.com/cross-domain-call.ashx?ref=jquery-jsonp-request&callback=jQuery1510993527567155793_137593181353

响应数据应该长这样:

 string callback = context.Request.QueryString["callback"];

 if (!string.IsNullOrEmpty(callback))
   context.Response.Write(string.Format("{0}({1});", callback, jc.Serialize(outputData)));
else
   context.Response.Write(jc.Serialize(outputData));

了解更多:使用jsonp内容类型进行jquery.ajax请求后出现解析错误

在此输入图像描述


3

有一个小错误 :) 您需要请求.js而不是.json。

$.ajax({
    dataType: 'jsonp',
    data: { api_key : apiKey },
    url: "http://de.dawanda.com/api/v1/" + resource + ".js",
    success: function(data) { console.log(data); },
    error: function(jqXHR, textStatus, errorThrown) { console.log(errorThrown); console.log(textStatus); }
});

啊,你有没有注意到,这个API有一个客户端?https://github.com/dawanda/dawanda-api-client-js


非常感谢您的回答!API现在运行得很好 :) 我一开始使用了API客户端,但我想坚持只使用jQuery方法。 - Thomas
你也可以使用jQuery客户端。它会自动检测Prototype或jQuery并使用给定的方法。(Y) - sdepold

1

尝试使用$.parseJSON将响应读入对象中:

success: function(data) {
    var json = $.parseJSON(data);
}

2
不,那样做不能解决使用jsonp内容类型的jQuery.ajax请求后出现的parsererror问题。 - Tom Stickel

1
你真的不应该在这里指定 jsonp。只需使用 json,因为你只是接收一个 JSON 字符串。 json(带填充的 json)期望执行一个 JavaScript 函数。在这种情况下,你需要在查询字符串中指定一个 "callback="。我猜这就是为什么 jQuery 也无法处理它的原因,因为有一个名为 callback 的属性。

如果我只使用json进行请求,那么我会得到一个空字符串作为答案。是API出了问题吗?如果是这样,有没有办法在js中绕过这个问题? - Thomas
2
你的意思是“jsonp(带填充的json)”,而不是“json(带填充的json)”。 - bear

1

确保所调用的服务能够以JsonP格式返回数据。

如果您正在使用asp.net webapi,可以使用开源项目WebApiContrib.Formatting.Jsonp。

请确保在WebApiConfig.Register中有以下行:

config.Formatters.Insert(0, new JsonpMediaTypeFormatter(new JsonMediaTypeFormatter(), "callback"));

我曾因此问题苦恼不已,希望这能对某些人有所帮助。


0

并非所有服务器都支持jsonp。它需要服务器在其结果中设置回调函数。我使用它来获取返回纯json但不支持jsonp(但将来可能会支持)的网站的json响应:

function AjaxFeed(){

    return $.ajax({
        url:            'http://somesite.com/somejsonfile.php',
        data:           {something: true},
        dataType:       'jsonp',

        /* Very important */
        contentType:    'application/json',
    });
}

function GetData()
    AjaxFeed()

    /* Everything worked okay. Hooray */
    .done(function(data){
        return data;
    })

    /* Okay jQuery is stupid manually fix things */
    .fail(function(jqXHR) {

        /* Build HTML and update */
        var data = jQuery.parseJSON(jqXHR.responseText);

        return data;
    });
}

3
我很希望这个能够起作用,因为它看起来相当聪明,但是'jqXHR.responseText'总是未定义的... - DanielST

0

我遇到的问题和你一样,直到我在url中添加了参数 "callback=?" 或 "c=?" 才解决了。

例如:"http://de.dawanda.com/api/v1/" + resource + ".json&c=?"

这可能会解决你的问题。它对我有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接