我试图使用fetch POST一个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 =等待取回('https://httpbin.org/post', {
方法:“文章”,
标题:{
“接受”:application / json,
“内容类型”:“application / json”
},
身体:JSON。stringify({a: 1, b: '文本内容'})
});
const content = await rawResponse.json();
console.log(内容);
}) ();
不能使用ES2017?参见@vp_art使用承诺的回答
然而,这个问题是由一个长期以来固定的chrome错误引起的问题。
以下是原来的答案。
chrome devtools甚至不显示JSON作为请求的一部分
这是真正的问题,这是chrome开发工具的一个bug,在chrome 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有效负载的端点,原始代码是正确的
有同样的问题-没有身体从客户端发送到服务器。
添加内容类型头为我解决了这个问题:
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 => {
...
})
如果你使用纯json REST API,我已经在fetch()周围创建了一个薄包装器,其中有许多改进:
// 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);
});
要使用它,你有变量api和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: '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'}
})
它可能对某些人有用:
我遇到的问题是,formdata没有为我的请求发送
在我的案例中,是以下标题的组合也导致了这个问题和错误的Content-Type。
我和请求一起发送了这两个头文件当我删除了工作的头文件时它并没有发送formdata。
"X-Prototype-Version": "1.6.1",
"X-Requested-With": "XMLHttpRequest"
另外,其他答案表明,Content-Type头需要正确。
对于我的请求,正确的Content-Type头是:
“内容类型”:“应用程序/ x-www-form-urlencoded;charset = utf - 8”
所以底线是,如果你的formdata没有附加到Request,那么它可能是你的header。试着减少标题,然后一个一个地添加它们,看看你的问题是否得到解决。