I'estou tentando POSTAR um objeto JSON usando fetch.
Pelo que posso entender, preciso de anexar um objecto de cordel ao corpo do pedido, por exemplo:
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) })
Ao utilizar [jsfiddle's json echo][2] I'd esperar ver o objeto I've enviado ({a: 1, b: 2}
) de volta, mas isso não acontece - os devtools cromados não'nem mesmo mostram o JSON como parte do pedido, o que significa que ele'não está sendo enviado.
Com o ES2017 suporte a 'async/await', esta é a forma de 'POSTAR' uma carga útil 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);
})();
Pode'não pode usar o ES2017? Veja @vp_art's resposta usando promessas
A questão, no entanto, é perguntar por um problema causado por um bug cromo há muito tempo atrás corrigido. A resposta original é a seguinte.
os devtools cromados não'nem sequer mostram o JSON como parte do pedido
Este é o verdadeiro problema aqui, e it's a bug with chrome devtools, corrigido no Chrome 46.
Esse código funciona bem - ele está PÔS o JSON corretamente, ele simplesmente não pode ser visto.
I'esperava ver o objecto I'esperava ver o objecto I'enviava de volta
that's não funciona porque esse não é o formato correcto para o JSfiddle's echo.
O [código correto][5] é:
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 ) ) })
Para os pontos finais que aceitam cargas úteis JSON, ** o código original está correcto***.
A partir dos motores de busca, acabei por me debruçar sobre este tópico para não colocar dados com o fetch, por isso pensei em adicionar isto.
Para non-json você não'não tem que usar dados de formulário. Você pode simplesmente definir o cabeçalho Content-Type' para
application/x-www-form-urlencoded' e utilizar uma 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'
});
Uma maneira alternativa de construir essa string corpo
, ao invés de digitá-la como eu fiz acima, é utilizar bibliotecas. Por exemplo, a função stringify' dos pacotes [
query-string'](https://www.npmjs.com/package/query-string) ou qs'. Assim, utilizando isto, pareceria:
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}
});
Depois de gastar algumas vezes, engenharia reversa jsFiddle, tentando gerar carga útil - há um efeito.
Por favor, tome cuidado na linha return response.json();
onde a resposta não é uma resposta - é uma promessa.
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:
&& Firefox > 39 && Chrome > 42