无法使用 Fetch API 获取 JSON,但可以使用 JQuery

Posted

技术标签:

【中文标题】无法使用 Fetch API 获取 JSON,但可以使用 JQuery【英文标题】:Unable to get JSON using Fetch API, but can using JQuery 【发布时间】:2018-03-17 17:53:35 【问题描述】:

我正在将一个 React 项目集成到一个 Grails/Angular 系统中,并且我正在尝试使用来自 React 的 Fetch API 来查询 Grails。

在应用程序运行和 Chrome 开发者工具控制台打开的情况下,以下操作按预期工作:

$.get('/project/controller/get', function(data, status) 
  console.log(data); 
);

它会显示一堆 JSON,如下所示:

以下内容无法按预期工作:

fetch('/project/controller/get', 
    credentials: 'include',
    headers: 
        'Content-Type': 'application/json'
    
)
.then(response => response.json())
.then(response => console.log(response))
.catch(error => console.log(error))

它给出了一个语法错误,因为它试图将 html 文档解析为 JSON。

在开发者工具网络选项卡中,我看到当我发出 JQuery 请求时,只有一个 GET 请求,而服务器响应是我想要的 JSON。

当我使用 Fetch API 发出请求时,会出现两个请求:

一个到 /project/controller/get,它只响应状态码 302,没有 JSON /project 的另一个响应状态码为 200,以及应用程序首页的 HTML。这是 Fetch API 接收并尝试解析为 JSON 的内容。

在执行 render as JSON 语句之前,我可以验证 Grails 控制器方法是否按预期生成数据。

使用 Axios 也会发生同样的事情。

JQuery 请求详情:

一般

请求网址:http://localhost:8080/project/controller/get

请求方法:GET

状态码:200 OK

远程地址:[::1]:8080

Referrer Policy:no-referrer-when-downgrade

响应标头

HTTP/1.1 200 正常

服务器:Apache-Coyote/1.1

内容类型:text/html;charset=utf-8

传输编码:分块

日期:格林威治标准时间 2017 年 10 月 6 日星期五 02:41:59

请求标头

GET /project/controller/get HTTP/1.1

主机:本地主机:8080

连接:保持活动

接受:/

X-Requested-With: XMLHttpRequest

用户代理:Mozilla/5.0(Windows NT 10.0;Win64;x64)AppleWebKit/537.36(KHTML,如 Gecko)Chrome/61.0.3163.100 Safari/537.36

推荐人:http://localhost:8080/project/settings/

接受编码:gzip、deflate、br

接受语言:en-GB,en;q=0.8,en-US;q=0.6,fr;q=0.4,ru;q=0.2

Cookie:JSESSIONID=52F86C47C43F558E05C2F6DB5E9E7CE2

有什么办法可以让它工作吗?谢谢。


我刚刚注意到在浏览器中输入 http://localhost:8080/project/controller/get 会自动将我重定向到 http://localhost:8080/project 出于某种原因。可能是服务器做了一些奇怪的事情,但奇怪的是 JQuery 请求有效......

【问题讨论】:

Content-Type header 用于指定请求正文的数据类型。由于您正在发出获取请求,因此您不需要它。尝试删除它。 “它给出了一个语法错误,因为它试图将 HTML 文档解析为 JSON。” 你能创建一个 jsfiddle jsfiddle.net 或 plnkr plnkr.co 来演示吗?见***.com/help/mcve 代码是否可能使用jQuery.ajaxSetup() 为Ajax 请求设置默认值?无论如何,对于您的 fetch 请求,您是否尝试过使用 headers: 'Accept': 'application/json' 或它的一些变体? (也就是说,为 GET 请求设置 Accept 标头,而不是为其设置 Content-Type ——正如前面评论中所指出的那样,这不会有任何影响。)当您在浏览器中查看请求的 devtools 时, jQuery $.get 调用正在发送,它发送的是什么 Accept 标头? 另外,您的 jquery 示例查询的 url 与您的 fetch 示例不同: 将标题更改为headers: 'Accept': 'application/json' 不会影响它。它仍然返回 HTML。 【参考方案1】:

它给出了一个语法错误,因为它试图解析一个 HTML 文档 作为 JSON。

如果响应是 HTML 使用 Response.text()

【讨论】:

是的,但问题是如何让它返回 JSON,因为通过 jQuery $.get() 查询相同的 URL 确实 返回 JSON。 @nnnnnn "假设通过 jQuery $.get() 查询相同的 URL 确实返回 JSON" 我们如何确定 "application/json" 已提供服务?如果响应是有效的JSON,OP 为什么会提到 HTML 文档? 该问题明确指出,对同一 URL 的请求会产生不同的响应,具体取决于它们使用的是 $.get() 还是 fetch()。他们还在控制台网络选项卡中看到不同的行为。这就是问题的全部意义所在。 @nnnnnn 不,这不是问题的重点。 OP 在问题文本中明确提到了 HTML document。 HTML 文档与JSON 有什么关系? OP 需要重现有效的JSONResponse.json() 调用时抛出错误。 啊,是的。微妙但重要。【参考方案2】:

302 是一个重定向,因此您的 fetch 请求被重定向到另一个页面,可能是登录页面 (?)

我在您的 fetch 请求中看到您正在使用 credentials:'include',这可能包括 Authorization 标头或类似内容,并且您的控制器正在拒绝该请求。

使用 chrome 开发者控制台,如果您在网络选项卡上标记“保留日志”,则可以检查请求

【讨论】:

以上是关于无法使用 Fetch API 获取 JSON,但可以使用 JQuery的主要内容,如果未能解决你的问题,请参考以下文章