jQuery getJSON 在本地工作,但不能跨域
我一直在寻找,但无法为我的问题找到明确的答案。所以就是这样。我有一个 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."
}
])
现在一切正常了!感谢您的帮助!
I've searched FOREVER and can't come up with a definitive answer to my problem. So here it is. I have a JSON file (I went to jsonlint to validate and it says its good) that looks like this (some information modified):
[{
"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"
}
]
I used jQuery to parse through and put on an html page using this function:
$.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');
});
It works perfectly! Now comes my issue, the JSON file will not be hosted locally, and will in fact be hosted on a separate domain. So I modified my code as follows (after some reading) hoping to get it working:
$.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');
});
By adding the 'callback' line I stopped getting a "Failed to load resource" error. However, nothing is happening. It is like the function I added isn't even there. I tried to take all of it out and add a simple 'alert(data)', but that didn't even fire. What am I doing wrong? A big problem is that I am 100% limited to just HTML and JavaScript to work (not my choice). Thanks for any help!
EDIT
Ok, I don't have ability for the other server to dynamically add anything to the json file. So I modified by hardcoding a function around the json (smaller sample):
storyData(
[{
"position":"1",
"category":"A",
"title":"Title to first story",
"description":"The first story."
}
])
Everything now works! Thanks for all the help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您需要查看 JSONP。
本质上,当您尝试从另一个域加载 JSON 时,它会失败,因为存在无法跨越的域边界。为了避免这种情况,您必须PAD它(JSONP 中的 P)。填充它本质上是将其包装在函数调用中(其中函数名称驻留在您的客户端上)。例如“正常”JSON 响应(例如 getjson.php):
带有
parseJSON 变为(例如 getjson.php?callback=parseJSON):
请注意 callback 中提供的值如何成为您的 JSON 响应现在包装的函数的名称.
然后你的客户将希望将其传递给
parseJSON
,这是您客户端上存在的一个函数(您已定义)。 jQuery(和其他库)尝试通过生成一些“随机”函数,然后通过原始回调发送回响应(所有这些都是在幕后完成的)来为您解决这个问题。如果您可以控制生成 JSON 的服务器页面,请实现一个回调方法,以便您可以提供 JSON 的包装方式,以便您可以在您的终端上使用它。 (仅当您处理来自客户端当前所在页面以外的域的数据时,才需要这样做)。
更新
要从根本上解决您遇到的问题,您需要找到一种方法将 JSON 信息放入 JSONP 调用中。在不知道“page.json”使用哪种语言的情况下,它应该包含以下伪代码逻辑:
如果您决定硬编码函数名称而不是允许它在 url 中作为“callback”提供,那么你需要记住它。对于下一个示例,假设我们将其命名为 MyJSONPCallback
现在,在您的客户端代码中,您可以继续使用:
You need to look in to JSONP.
Essentially, when you try to load JSON from another domain, it fails because there is a domain boundary you can not cross. To avoid this, you have to PAD it (P in JSONP). Padding it is essentially wrapping it in a function call (where the function name resides on your client.) e.g. a "normal" JSON response (say, for example, getjson.php):
JSON with a callback of
parseJSON
becomes (Say, for example, getjson.php?callback=parseJSON):Notice how the value that was supplied in callback becomes the name of the function your JSON response is now wrapped in.
Then your client will want to pass it to
parseJSON
, a function that exists on your client (that you've defined). jQuery (and other libraries) try to take care of this for you by generating some "random" function and then sending the response back through your original callback (all this is done under the hood).If you have control over the server page generating the JSON, implement a callback method so you can supply how the JSON should be wrapped so you can then work with it on your end. (This is only necessary when you're dealing with data from a domain other than the page the client is currently on).
UPDATE
To basically solve the problem you're having, you need to find a way to get your JSON information in to a JSONP call. Without knowing what language your "page.json" is in, here's the pseudo-code logic that it should contain:
If you decide to hard-code the function name instead of allow it to be supplied in the url as "callback", then you need to remember it. For the next example, let's imagine we named it MyJSONPCallback
Now, in your client code, you can go ahead of use:
对于那些使用 MVC ActionResult 生成 JSONP 的人来说,ASP.NET MVC 并未提供开箱即用的 JSONP 支持,但可以轻松添加:
http://nikcodes.com/2012/02/29/an-asp-net-mvc-jsonp-actionresult
For those using MVC ActionResult to generate JSONP, ASP.NET MVC does not ship with JSONP support out of the box, but it is easy to add with:
http://nikcodes.com/2012/02/29/an-asp-net-mvc-jsonp-actionresult
浏览器不允许将此作为安全措施。您可以查看 JSONP 作为解决此问题的方法,尽管这是一个巨大的安全风险,因为它依赖于运行您从中获取 JSON 文本的域提供的 javascript。
Browsers don't let this work as a security measure. You could check out JSONP as a way to get around this, though it is a HUGE security risk since it relies on running javascript supplied by the domain you are getting the JSON text from.
我没有深入研究这个问题,但我相信您的问题与同域策略有关...您可能想研究一下:http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/
I have not looked deeply into this issue, but I believe your problem relates to the same-domain-policy... you might want to look into this though : http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/
请参阅这篇文章——您必须提供一个封装在函数中的有效 javascript 对象。
http://en.wikipedia.org/wiki/JSONP
你想要返回类似的内容:
parseResponse({"Name": "Cheeso", "Id" : 1823, "Rank": 7})
但是你的服务器端方法需要知道返回它,而不仅仅是返回里面有 JSON。 jQuery 所做的只是自动生成一个函数名称(
callback
参数中的?
),然后评估从服务器返回的“函数”。服务器使用内部包含的 JSON 创建函数调用。See this article -- you have to supply a valid javascript object wrapped in a function.
http://en.wikipedia.org/wiki/JSONP
You'd want to return something like:
parseResponse({"Name": "Cheeso", "Id" : 1823, "Rank": 7})
But your server-side method would need to know to return that, instead of just the JSON inside. All jQuery does is auto-generate a function name (the
?
in thecallback
parameter) and then eval the "function" that's returned from the server. The server creates the function call with the JSON contained inside.Brad Christie 的回答帮助我快速让我的代码运行起来。我在这里创建一个新条目,因为它比其他解决方案简单一点。
以下是我从 http://localhost:5000 运行的代码 -
从 http://localhost:3000/auget_from_server,我返回以下 JSON 作为响应(这部分特定于流星,但它适用于非流星服务器也) -
这会在日志中打印以下内容 -
Brad Christie's answer helped me quickly get my code working. I am creating a new entry here since it is little simpler than the other solutions.
Following is the code that I run from http://localhost:5000 -
From the location at http://localhost:3000/auget_from_server, I return the following JSON in response (this part is specific to meteor but it will work for non-meteor servers also) -
This prints the following in the logs -