it-swarm.com.de

Fetch: POST json data

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.

424
Razor

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

427
Razor

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));
171
vp_arth

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}
});
_
42
Noitidart

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

35

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');
});
16

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 => {
   ...
})
11
Green

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'}
})
10
Marcus Lind

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);
    });
}
4
lama12345

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.

3
user_CC

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 POSTed ist.

3
Eric Sellin