本文翻译自:Fetch: POST json data
I'm trying to POST a JSON object using fetch . 我正在尝试使用fetch发布 JSON对象。
From what I can understand, I need to attach a stringified object to the body of the request, eg: 据我了解,我需要将一个字符串化的对象附加到请求的主体,例如:
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) })
When using jsfiddle's json echo I'd expect to see the object I've sent ( {a: 1, b: 2}
) back, but this does not happen - chrome devtools doesn't even show the JSON as part of the request, which means that it's not being sent. 当使用jsfiddle的json回显时,我希望能看到已发送的对象( {a: 1, b: 2}
),但这不会发生-chrome devtools甚至不显示JSON作为请求的一部分,这表示它没有被发送。
#1楼
参考:https://stackoom.com/question/20w2n/提取-POST-json数据
#2楼
After spending some times, reverse engineering jsFiddle, trying to generate payload - there is an effect. 花了一些时间后,对jsFiddle进行反向工程,尝试生成有效负载-会产生效果。
Please take eye (care) on line return response.json();
请注意行return response.json();
where response is not a response - it is promise. 回应不是回应,而是承诺。
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 jsFiddle: http : //jsfiddle.net/egxt6cpz/46/ && Firefox> 39 && Chrome> 42
#3楼
With ES2017 async/await
support , this is how to POST
a JSON payload: 随着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); })();
Can't use ES2017? 无法使用ES2017? See @vp_art's answer using promises 参见@vp_art 使用诺言的答案
The question however is asking for an issue caused by a long since fixed chrome bug. 但是,问题是由很久以来修复的chrome bug引起的。
Original answer follows. 原始答案如下。
chrome devtools doesn't even show the JSON as part of the request chrome devtools甚至没有在请求中显示JSON
This is the real issue here , and it's a bug with chrome devtools , fixed in Chrome 46. 这是真正的问题 , 这是 Chrome 46中修复的chrome devtools的错误 。
That code works fine - it is POSTing the JSON correctly, it just cannot be seen. 该代码可以正常工作-它正确地发布了JSON,只是看不到。
I'd expect to see the object I've sent back 我希望看到我寄回的物品
that's not working because that is not the correct format for JSfiddle's echo . 那是行不通的,因为那不是JSfiddle的echo的正确格式 。
The correct code is: 正确的代码是:
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 ) ) })
For endpoints accepting JSON payloads, the original code is correct 对于接受JSON有效负载的端点, 原始代码是正确的
#4楼
From search engines, I ended up on this topic for non-json posting data with fetch, so thought I would add this. 在搜索引擎上,我最终讨论了通过fetch进行非json发布数据的问题,因此我想添加此内容。
For non-json you don't have to use form data. 对于非json,您不必使用表单数据。 You can simply set the Content-Type
header to application/x-www-form-urlencoded
and use a string: 您可以简单地将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'
});
An alternative way to build that body
string, rather then typing it out as I did above, is to use libraries. 构建该body
字符串的另一种方法是使用库,而不是像我上面那样键入它。 For instance the stringify
function from query-string
or qs
packages. 例如,来自query-string
或qs
包的stringify
函数。 So using this it would look like: 因此,使用它看起来像:
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}
});
#5楼
I think your issue is jsfiddle
can process form-urlencoded
request only. 我认为您的问题是jsfiddle
只能处理form-urlencoded
请求。
But correct way to make json request is pass correct json
as a body: 但是发出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));
#6楼
I have created a thin wrapper around fetch() with many improvements if you are using a purely json REST API: 如果您使用的是纯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);
});
To use it you have the variable api
and 4 methods: 要使用它,您需要使用变量api
和4种方法:
api.get('/todo').then(all => { /* ... */ });
And within an async
function: 在async
函数中:
const all = await api.get('/todo');
// ...
Example with jQuery: 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');
});