无法使用 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的主要内容,如果未能解决你的问题,请参考以下文章

Fetch Api 无法从 PHP 服务器获取 Session

使用 Fetch API 获取 json 格式的闪烁提要

html JS.JSON。使用fetch API获取远程JSON数据

使用 fetch、cors 时如何从 json API 获取属性?

无法使用 fetch API 请求带有 HTML 页面的 localhost 节点服务器

React Fetch:获取json结果但显示网络错误