jQuery getJSON在本地工作,但不是跨域

时间:2011-07-27 19:05:08

标签: jquery json cross-domain jsonp getjson

我已经搜索过FOREVER,无法对我的问题做出明确的答案。所以这就是。我有一个JSON文件(我去jsonlint验证,它说它很好)看起来像这样(修改了一些信息):

[{
        "position":"1",
        "category":"A",
        "title":"Title to first story",
        "description":"The first story."
    },
    {
        "position":"2",
        "category":"B",
        "title":"Title to second story",
        "description":"The second story"
    },
    {
        "position":"3",
        "category":"B",
        "title":"Title to third story",
        "description":"The third story"
    }
]

我使用jQuery解析并使用此函数放置一个html页面:

$.getJSON('page.json', function(data) {
  var items = [];

  $.each(data.reponse, function(item, i) {
    items.push('<li id="' + i.position + '">' + i.title + ' - ' + i.description + '</li>');
  });

  $('<ul/>', {
    'class': 'my-new-list',
    html: items.join('')
  }).appendTo('body');
});

完美无缺!现在我的问题是,JSON文件不会在本地托管,实际上将托管在一个单独的域上。所以我修改了我的代码如下(经过一些阅读)希望能让它工作:

$.getJSON('http://www.otherdomain.com/page.json?format=json&callback=?', function(data) {
  var items = [];

  $.each(data.reponse, function(item, i) {
    items.push('<li id="' + i.position + '">' + i.title + ' - ' + i.description + '</li>');
  });

  $('<ul/>', {
    'class': 'my-new-list',
    html: items.join('')
  }).appendTo('body');
});

通过添加“回调”行,我停止了“无法加载资源”错误。然而,一切都没有发生。这就像我添加的功能甚至不存在。我试图把它全部拿出来并添加一个简单的“警报(数据)”,但这甚至没有发射。我究竟做错了什么?一个大问题是我100%仅限于HTML和JavaScript工作(不是我的选择)。谢谢你的帮助!

修改 好吧,我没有能力让其他服务器动态添加任何内容到json文件。所以我通过在json(较小的样本)周围硬编码函数来修改:

storyData(
[{
        "position":"1",
        "category":"A",
        "title":"Title to first story",
        "description":"The first story."
    }
])

现在一切正常!谢谢你的帮助!

6 个答案:

答案 0 :(得分:15)

您需要查看JSONP

基本上,当您尝试从另一个域加载JSON时,它会失败,因为您无法跨越域边界。要避免这种情况,您必须 PAD (PSON在JSONP中)。填充它实际上是将它包装在函数调用中(函数名称驻留在客户端上)。一个“正常”的JSON响应(例如,getjson.php):

{foo:'bar'}

回调为parseJSON的JSON变为(比方说,例如,getjson.php?callback = parseJSON):

parseJSON({foo:'bar'})

请注意回调中提供的值如何成为您的JSON响应现在包含在其中的函数的名称。

然后您的客户端会希望将其传递给parseJSON,这是您客户端上已存在的功能(已定义)。 jQuery(和其他库)尝试通过生成一些“随机”函数然后通过原始回调发送响应来为您处理这一切(所有这些都在引擎盖下完成)。

如果您可以控制生成JSON的服务器页面,请实现一个回调方法,以便您可以提供如何包装JSON,以便您可以在最后使用它。 (仅当您处理来自客户端当前所在页面以外的域的数据时,才需要这样做。)


更新

要基本解决您遇到的问题,您需要找到一种方法将JSON信息传入JSONP调用。不知道你的“page.json”是什么语言,这里是它应该包含的伪代码逻辑:

if GET_VARIABLE("callback") is supplied

  print GET_VARIABLE("callback") and an open parenthesis
  print normal JSON data
  print closing parenthesis

else

  print normal JSON data

end if

如果你决定硬编码函数名而不是允许它在url中作为“回调”提供,那么你需要记住它。对于下一个示例,让我们假设我们将其命名为 MyJSONPCallback

现在,在您的客户端代码中,您可以继续使用:

$.ajax({
  url: 'http://anotherdomain.com/page.json?format=json',
  dataType: 'json',
  jsonpCallback: 'MyJSONPCallback', // specify the callback name if you're hard-coding it
  success: function(data){
    // we make a successful JSONP call!
  }
});

答案 1 :(得分:2)

对于那些使用MVC ActionResult来生成JSONP的人来说,ASP.NET MVC并没有提供开箱即用的JSONP支持,但它很容易添加:

http://nikcodes.com/2012/02/29/an-asp-net-mvc-jsonp-actionresult

答案 2 :(得分:0)

浏览器不会将此作为安全措施。您可以查看JSONP作为解决此问题的方法,尽管这是一个巨大的安全风险,因为它依赖于运行您从JSON文本获取的域提供的javascript。

答案 3 :(得分:0)

我没有仔细研究过这个问题,但我认为你的问题与同域策略有关......你可能想要研究一下这个问题:http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/

答案 4 :(得分:0)

请参阅此文章 - 您必须提供包含在函数中的有效javascript对象。

http://en.wikipedia.org/wiki/JSONP

您想要返回类似的内容:

parseResponse({"Name": "Cheeso", "Id" : 1823, "Rank": 7})

但是你的服务器端方法需要知道返回它,而不仅仅是内部的JSON。所有jQuery都会自动生成一个函数名(?参数中的callback),然后评估从服务器返回的“函数”。服务器使用里面包含的JSON创建函数调用。

答案 5 :(得分:0)

Brad Christie的回答帮助我快速完成了我的代码工作。我在这里创建了一个新条目,因为它比其他解决方案简单得多。

以下是我从http://localhost:5000 -

运行的代码
(function() {
        var api = "http://www.localhost:3000/auget_from_server?format=json";
        var request = $.getJSON( api, {
            secret : 'secret', 
            appId : 'app', 
            emailId : 'abc@gmail.com',
            async: false,
            dataType : 'json',
          },
          function(data, result){
            $("div.some_div").append(JSON.stringify(data));
          });

        request.complete(function(d, status){
            console.log('Complete the request and got the data - ' + JSON.stringify(d) + '/' + status, filename);
        });

        request.error(function(err){
            console.log('Error happened - ', filename);
            console.log(err);
        });

        request.success(function( data, status, jqXHR ) {
            $("div.some_div").append(data);
        });


        })();

http://localhost:3000/auget_from_server的位置,我返回以下JSON作为响应(此部分特定于meteor,但它也适用于非流星服务器) -

this.response.writeHead('200', {'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'});
this.response.end(JSON.stringify([{'works_or_not' : 'works', 'name' : 'akaushik', 'application' : 'Qoll', 'message' : 'hello from server', 'currentTime' : dt+''}]));

这将在日志中打印以下内容 -

Complete the request and got the data - {"readyState":4,"responseText":"[{\"works_or_not\":\"works\",\"name\":\"akaushik\",\"application\":\"Qoll\",\"message\":\"hello from server\",\"currentTime\":\"Tue Dec 15 2015 23:59:14 GMT-0500 (EST)\"}]","responseJSON":[{"works_or_not":"works","name":"akaushik","application":"Qoll","message":"hello from server","currentTime":"Tue Dec 15 2015 23:59:14 GMT-0500 (EST)"}],"status":200,"statusText":"OK"}/success
相关问题