Fetch: POST JSON data



Я пытаюсь опубликовать объект JSON с помощью fetch.



из того, что я могу понять, мне нужно прикрепить строковый объект к телу запроса, например:



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) })


при использовании JSON echo jsfiddle Я ожидал бы увидеть объект, который я послал ({a: 1, b: 2}) назад, но этого не происходит - chrome devtools даже не показывает JSON как часть запроса, что означает, что он не отправляется.

954   11  

11 ответов:

С 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);
})();

не может использовать ES2017? См. @vp_art по ответ с помощью обещаний

вопрос, однако, задает вопрос, вызванный давно Исправлена ошибка chrome.
Оригинальный ответ следует.

chrome devtools даже не показывает JSON как часть запрос

это реальная проблема здесь и ошибка с chrome devtools, исправлено в Chrome 46.

этот код отлично работает - он правильно отправляет JSON, его просто нельзя увидеть.

Я ожидал бы увидеть объект, который я отправил обратно

это не работает, потому что это не правильный формат для Эха JSfiddle.

The исправить код - это:

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,исходный код правильный

Я думаю, что ваша проблема jsfiddle может процесс form-urlencoded запрос только.

но правильный способ сделать запрос 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));

из поисковых систем я попал в эту тему для публикации данных без json с помощью fetch, поэтому подумал, что добавлю это.

на non-json вам не нужно использовать данные формы. Вы можете просто установить 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'
});

альтернативный способ построить это body строка, а не вводить его, как я сделал выше, чтобы использовать библиотеки. Например,

потратив несколько раз, обратный инжиниринг jsFiddle, пытаясь генерировать полезную нагрузку-есть эффект.

Пожалуйста, обратите внимание (уход) на линии return response.json(); где ответ не является ответом-это обещание.

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

Я создал тонкую обертку вокруг fetch () со многими улучшениями, если вы используете чисто JSON REST API:

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

была та же проблема - нет body был отправлен с клиента на сервер.

добавлять Content-Type заголовок решил это за меня:

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

это связано с Content-Type. Как вы могли заметить из других обсуждений и ответов на этот вопрос, некоторые люди смогли решить его, установив 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 не был отправлен для моего запроса

в моем случае это была комбинация следующих заголовков, которые также вызывали проблему и неправильный тип контента.

поэтому я отправлял эти два заголовка с запросом, и он не отправлял formdata, когда я удалял заголовки, которые работали.

"X-Prototype-Version" : "1.6.1",
"X-Requested-With" : "XMLHttpRequest"

также как и другие ответы свидетельствуют, что Заголовок типа контента должен быть правильным.

для моего запроса правильный заголовок Content-Type был:

"Content-Type": "application / x-www-form-urlencoded; charset=UTF-8"

Итак, если ваши formdata не прикрепляются к запросу, то это могут быть ваши заголовки. Попробуйте свести ваши заголовки к минимуму, а затем попробуйте добавить их один за другим, чтобы увидеть, если ваша проблема решена.

верхний ответ не работает для PHP7, потому что он имеет неправильную кодировку, но я мог бы выяснить правильную кодировку с другими ответами. Этот код также отправляет файлы cookie аутентификации, которые вы, вероятно, хотите, когда имеете дело, например, с форумами PHP:

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

если ваша полезная нагрузка JSON содержит массивы и вложенные объекты, я бы использовал URLSearchParams и jQuery param() метод.

fetch('/somewhere', {
  method: 'POST',
  body: new URLSearchParams($.param(payload))
})

для вашего сервера это будет выглядеть как стандартный HTML <form> будучи POSTed.

Я думаю, что нам не нужно разбирать объект JSON в строку, если удаленный сервер принимает json в их запрос, просто запустите:

const request = await fetch ('/echo/json', {
  headers: {
    'Content-type': 'application/json'
  },
  method: 'POST',
  body: { a: 1, b: 2 }
});

как запрос скручивания

curl -v -X POST -H 'Content-Type: application/json' -d '@data.json' '/echo/json'

в случае, если удаленная служба не принимает файл json в качестве тела, просто отправьте форму данных:

const data =  new FormData ();
data.append ('a', 1);
data.append ('b', 2);

const request = await fetch ('/echo/form', {
  headers: {
    'Content-type': 'application/x-www-form-urlencoded'
  },
  method: 'POST',
  body: data
});

как запрос скручивания

curl -v -X POST -H 'Content-type: application/x-www-form-urlencoded' -d '@data.txt' '/echo/form'

Comments

    Ничего не найдено.