Fetch: POST json data
我尝试使用fetch发布一个JSON对象。
据我所知,我需要在请求的主体上附加一个字符串化的对象,例如:
1 2 3 4 5 6 7 8 9 10 11 | 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 echo时,我希望看到我发送的对象(
有了ES2017
1 2 3 4 5 6 7 8 9 10 11 12 13 | (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?使用承诺查看@vpart的答案
然而,这个问题要求解决一个长期以来修复的chrome错误引起的问题。原始答案如下。
chrome devtools doesn't even show the JSON as part of the request
这是真正的问题,这是chrome devtools的一个bug,在chrome 46中修复。
这段代码工作得很好——它正确地发布了JSON,只是看不到它。
I'd expect to see the object I've sent back
这不起作用,因为这不是jfiddle echo的正确格式。
正确的代码是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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有效负载的端点,原始代码是正确的。
我认为你的问题是
但是,提出JSON请求的正确方法是将正确的
1 2 3 4 5 6 7 8 9 | 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)); |
在搜索引擎中,我以非JSON发布带有fetch的数据结束了这个主题,所以我想添加这个主题。
对于非JSON,您不必使用表单数据。您只需将
1 2 3 4 5 | 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' }); |
另一种构建
1 2 3 4 5 6 | 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} }); |
在花费了一些时间之后,逆向工程JSfiddle,尝试生成有效负载——这是一个效果。
请注意在线
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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); }); |
jfiddle:http://jsfiddle.net/egxt6cpz/46/&;firefox>39&;chrome>42
如果您使用的是纯JSON REST API,那么我已经创建了一个fetch()的瘦包装器,并进行了许多改进:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // 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); }); |
要使用它,您可以使用变量
1 | api.get('/todo').then(all => { /* ... */ }); |
在
1 2 | const all = await api.get('/todo'); // ... |
jquery示例:
1 2 3 4 5 6 7 8 | $('.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'); }); |
如果有同样的问题-没有从客户机向服务器发送
添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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 => { ... }) |
这与
但是,如果您尝试使用jquery的
1 2 3 4 5 6 7 | 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'} }) |
如果您的JSON负载包含数组和嵌套对象,我将使用
1 2 3 4 | fetch('/somewhere', { method: 'POST', body: new URLSearchParams($.param(payload)) }) |
在您的服务器上,这看起来像一个标准的html