协慌网

登录 贡献 社区

提取:POST JSON 数据

我正在尝试使用fetch 发布JSON 对象。

据我了解,我需要将一个字符串化的对象附加到请求的主体,例如:

fetch("/echo/json/",
{
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    method: "POST",
    body: JSON.stringify({a: 1, b: 2})
})
.then(function(res){ console.log(res) })
.catch(function(res){ console.log(res) })

当使用jsfiddle 的 JSON 回显时,我希望能看到已发送的对象( {a: 1, b: 2} ),但这不会发生 - chrome devtools 甚至不显示 JSON 作为请求的一部分,这表示它没有被发送。

答案

随着 ES2017 async/await的支持,这是如何POST一个 JSON 有效载荷:

(async () => {
  const rawResponse = await fetch('https://httpbin.org/post', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({a: 1, b: 'Textual content'})
  });
  const content = await rawResponse.json();

  console.log(content);
})();

无法使用 ES2017?参见 @vp_art使用 promise 的答案

但是,问题是由很久以来修复的 chrome bug 引起的。
原始答案如下。

chrome devtools 甚至没有在请求中显示 JSON

这是真正的问题,这是 Chrome 46 中修复的 chrome devtools 的错误。

该代码可以正常工作 - 它正确地发布了 JSON,只是看不到它。

我希望能看到我寄回的物件

那是行不通的,因为那不是JSfiddle 的 echo的正确格式。

正确的代码是:

var payload = {
    a: 1,
    b: 2
};

var data = new FormData();
data.append( "json", JSON.stringify( payload ) );

fetch("/echo/json/",
{
    method: "POST",
    body: data
})
.then(function(res){ return res.json(); })
.then(function(data){ alert( JSON.stringify( data ) ) })

对于接受 JSON 有效负载的端点,原始代码是正确的

我认为您的问题是jsfiddle可以处理form-urlencoded请求。

但是发出 json 请求的正确方法是将正确的json作为主体传递:

fetch('https://httpbin.org/post', {
  method: 'post',
  headers: {
    'Accept': 'application/json, text/plain, */*',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({a: 7, str: 'Some string: &=&'})
}).then(res => res.json())
  .then(res => console.log(res));

在搜索引擎中,我最终遇到了有关使用 fetch 进行非 json 发布数据的问题,因此我想添加此内容。

对于非 json,您不必使用表单数据。您可以简单地将Content-Type标头设置为application/x-www-form-urlencoded并使用字符串:

fetch('url here', {
    method: 'POST',
    headers: {'Content-Type':'application/x-www-form-urlencoded'}, // this line is important, if this content-type is not set it wont work
    body: 'foo=bar&blah=1'
});

body字符串的另一种方法是使用库,而不是像我上面所做的那样将其键入。例如,来自query-stringqsstringify因此,使用它看起来像:

import queryString from 'query-string'; // import the queryString class

fetch('url here', {
    method: 'POST',
    headers: {'Content-Type':'application/x-www-form-urlencoded'}, // this line is important, if this content-type is not set it wont work
    body: queryString.stringify({for:'bar', blah:1}) //use the stringify object of the queryString class
});