Ich versuche, ein JSON-Objekt mit fetch zu POST.
Nach allem, was ich verstehen kann, muss ich ein stringiertes Objekt an den Hauptteil der Anfrage anhängen, z.
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) })
Bei Verwendung von jsfiddles json echo würde ich erwarten, das Objekt zu sehen, das ich zurückgesendet habe ({a: 1, b: 2}
), aber das passiert nicht - chrome devtools nicht zeigt sogar den JSON als Teil der Anfrage an, was bedeutet, dass er nicht gesendet wird.
Mit ES2017 _async/await
_ support können Sie eine JSON-Nutzlast folgendermaßen POST
:
_(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 kann nicht verwendet werden? Siehe @ vp_arts Antwort mit Versprechen
Bei der Frage handelt es sich jedoch um ein Problem, das durch einen längst behobenen chrome Fehler verursacht wurde.
Es folgt die ursprüngliche Antwort.
chrome devtools zeigt JSON nicht einmal als Teil der Anfrage an
Dies ist das eigentliche Problem hier , und es ist ein Fehler mit chrome devtools , behoben in Chrome 46.
Dieser Code funktioniert einwandfrei - er postet den JSON korrekt, er kann einfach nicht gesehen werden.
Ich würde erwarten, das Objekt zu sehen, das ich zurückgeschickt habe
das funktioniert nicht, weil das nicht das richtige Format für JSfiddles Echo ist .
Der richtige Code lautet:
_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 ) ) })
_
Für Endpunkte, die JSON-Nutzdaten akzeptieren , ist der ursprüngliche Code korrekt
Ich denke, Ihr Problem ist jsfiddle
kann nur die Anforderung form-urlencoded
verarbeiten.
Aber der richtige Weg, eine JSON-Anfrage zu stellen, ist, json
als Body zu übergeben:
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));
Von Suchmaschinen bin ich auf dieses Thema gestoßen, um Daten mit Fetch zu veröffentlichen, die nicht von JSON stammen. Daher dachte ich, ich würde dies hinzufügen.
Für Nicht-JSON müssen Sie keine Formulardaten verwenden. Sie können einfach den Header _Content-Type
_ auf _application/x-www-form-urlencoded
_ setzen und eine Zeichenfolge verwenden:
_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'
});
_
Eine alternative Möglichkeit, die Zeichenfolge body
zu erstellen, anstatt sie wie oben beschrieben einzugeben, ist die Verwendung von Bibliotheken. Zum Beispiel die Funktion stringify
aus query-string
oder qs
Paketen. Also würde es so aussehen:
_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}
});
_
Nachdem Sie einige Zeit mit dem Reverse Engineering von jsFiddle verbracht haben und versucht haben, Nutzlast zu generieren, gibt es einen Effekt.
Bitte achten Sie auf die Zeile return response.json();
, in der die Antwort keine Antwort ist - sie ist ein Versprechen.
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
Ich habe einen dünnen Wrapper um fetch () mit vielen Verbesserungen erstellt, wenn Sie eine reine json REST -API verwenden:
// 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);
});
Um es zu benutzen, haben Sie die Variable api
und 4 Methoden:
api.get('/todo').then(all => { /* ... */ });
Und innerhalb einer async
-Funktion:
const all = await api.get('/todo');
// ...
Beispiel mit 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');
});
Hatte das gleiche Problem - es wurde kein body
von einem Client an einen Server gesendet.
Das Hinzufügen des Headers Content-Type
hat es für mich gelöst:
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 => {
...
})
Dies hängt mit Content-Type
zusammen. Wie Sie vielleicht aus anderen Diskussionen und Antworten auf diese Frage bemerkt haben, konnten einige Leute sie lösen, indem sie Content-Type: 'application/json'
setzten. Leider hat es in meinem Fall nicht geklappt, meine POST Anfrage war auf der Serverseite noch leer.
Wenn Sie es jedoch mit jQueries $.post()
versuchen und es funktioniert, liegt dies wahrscheinlich daran, dass jQuery Content-Type: 'x-www-form-urlencoded'
anstelle von application/json
verwendet.
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'}
})
Die Top-Antwort funktioniert in PHP7 nicht, da die Codierung falsch ist, aber ich könnte die richtige Codierung mit den anderen Antworten herausfinden. Dieser Code sendet auch Authentifizierungs-Cookies, die Sie wahrscheinlich benötigen, wenn Sie z. PHP Foren:
Julia = function(juliacode) {
fetch('Julia.php', {
method: "POST",
credentials: "include", // send cookies
headers: {
'Accept': 'application/json, text/plain, */*',
//'Content-Type': 'application/json'
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" // otherwise $_POST is empty
},
body: "juliacode=" + encodeURIComponent(juliacode)
})
.then(function(response) {
return response.json(); // .text();
})
.then(function(myJson) {
console.log(myJson);
});
}
Es könnte für jemanden nützlich sein:
Ich hatte das Problem, dass keine Formulardaten für meine Anfrage gesendet wurden
In meinem Fall war es eine Kombination der folgenden Header, die ebenfalls das Problem und den falschen Inhaltstyp verursachten.
Also habe ich diese beiden Header mit der Anfrage gesendet und die Formulardaten wurden nicht gesendet, als ich die funktionierenden Header entfernt habe.
"X-Prototype-Version" : "1.6.1", "X-Requested-With" : "XMLHttpRequest"
Auch wenn andere Antworten darauf hindeuten, dass der Content-Type-Header korrekt sein muss.
Für meine Anfrage lautete der richtige Content-Type-Header:
"Content-Type": "application/x-www-form-urlencoded; charset = UTF-8"
Unterm Strich könnten Ihre Formulardaten also möglicherweise Ihre Kopfzeilen sein, wenn sie nicht an die Anfrage angehängt werden. Versuchen Sie, die Überschriften auf ein Minimum zu beschränken, und fügen Sie sie dann nacheinander hinzu, um festzustellen, ob Ihr Problem behoben ist.
Wenn Ihre JSON-Nutzdaten Arrays und verschachtelte Objekte enthalten, würde ich URLSearchParams
und die param()
-Methode von jQuery verwenden.
fetch('/somewhere', {
method: 'POST',
body: new URLSearchParams($.param(payload))
})
Für Ihren Server sieht dies aus wie ein Standard-HTML <form>
, der POST
ed ist.