取:POST JSON数据

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

从我所能理解的,我需要附加一个string化的对象到请求的主体,例如:

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作为请求的一部分,这意味着它没有被发送。

铬devtools甚至不显示JSON作为请求的一部分

这是真正的问题 ,这是一个铬铬devtools的bug ,在46固定。

该代码工作正常 – 它是正确的发布JSON,它只是不能被看到。

我希望看到我发回的对象

这不工作,因为这不是JSfiddle的回声正确的格式 。

正确的代码是:

 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)); 

花了一些时间后,反向工程jsFiddle,试图产生有效载荷 – 有一个效果。

请注意线上( return response.json(); 答复不是答复 – 这是承诺。

 var json = { json: JSON.stringify({ a: 1, b: 2 }), delay: 3 }; fetch('/echo/json/', { method: 'post', headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' }, body: 'json=' + encodeURIComponent(JSON.stringify(json.json)) + '&delay=' + json.delay }) .then(function (response) { return response.json(); }) .then(function (result) { alert(result); }) .catch (function (error) { console.log('Request failed', error); }); 

jsFiddle: http : //jsfiddle.net/egxt6cpz/46/ && Firefox> 39 && Chrome> 42

从search引擎,我结束了这个主题非json张贴数据与提取,所以想我会补充这一点。

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

 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' }); 

构build这个bodystring的另一种方法,就是像上面那样input,就是使用库。 例如query-stringqs包中的stringify函数。 所以使用它将看起来像:

 import queryString from 'query-string'; 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} }); 

如果您使用的是纯粹的json REST API,我已经在fetch()方面创build了一个很小的包装器,并有许多改进:

 // Small library to improve on fetch() usage const api = function(method, url, data, headers = {}){ return fetch(url, { method: method.toUpperCase(), body: JSON.stringify(data), // send it as stringified json credentials: api.credentials, // to keep the session on the request headers: Object.assign(api.headers, headers) // extend the headers }).then(res => res.ok ? res.json() : Promise.reject(res)); }; // Defaults that can be globally overwritten api.credentials = 'include'; api.headers = { 'csrf-token': window.csrf || '', // only if globally set, otherwise ignored 'Accept': 'application/json', // receive json 'Content-Type': 'application/json' // send json }; // Convenient methods ['get', 'post', 'put', 'delete'].forEach(method => { api[method] = api.bind(null, method); }); 

要使用它你有variablesapi和4种方法:

 api.get('/todo').then(all => { /* ... */ }); 

在一个async函数中:

 const all = await api.get('/todo'); // ... 

jQuery示例:

 $('.like').on('click', async e => { const id = 123; // Get it however it is better suited await api.put(`/like/${id}`, { like: true }); // Whatever: $(e.target).addClass('active dislike').removeClass('like'); }); 

这与Content-Type 。 正如你可能已经从其他讨论和这个问题的答案中注意到的,有些人可以通过设置Content-Type: 'application/json'来解决它。 不幸的是,在我的情况下,它不工作,我的POST请求仍然在服务器端是空的。

然而,如果你尝试使用jQuery的$.post()并且它正在工作,原因可能是因为jQuery使用Content-Type: 'x-www-form-urlencoded'而不是application/json

 data = Object.keys(data).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key])).join('&') fetch('/api/', { method: 'post', credentials: "include", body: data, headers: {'Content-Type': 'application/x-www-form-urlencoded'} }) 

有同样的问题 – 没有body从客户端发送到服务器。

添加Content-Type标题为我解决了它:

 var headers = new Headers(); headers.append('Accept', 'application/json'); // This one is enough for GET requests headers.append('Content-Type', 'application/json'); // This one sends body return fetch('/some/endpoint', { method: 'POST', mode: 'same-origin', credentials: 'include', redirect: 'follow', headers: headers, body: JSON.stringify({ name: 'John', surname: 'Doe' }), }).then(resp => { ... }).catch(err => { ... })