Я'пытаюсь отправить объект 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) })
При использовании [jsfiddle's json echo][2] я'ожидаю увидеть обратно объект, который я'отправил ({a: 1, b: 2}
), но этого не происходит - chrome devtools даже не показывает JSON как часть запроса, что означает, что он'не отправляется.
С поддержкой 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's ответ с использованием обещаний
Однако вопрос задан для проблемы, вызванной * давно исправленной ошибкой в хроме. Оригинальный ответ следует ниже.
chrome devtools даже не показывает JSON как часть запроса
Это реальная проблема, и это ошибка в chrome devtools, исправленная в Chrome 46.
Этот код работает нормально - он правильно размещает JSON, просто его не видно.
Я ожидаю увидеть объект, который я отправил обратно.
это не работает, потому что это не правильный формат для JSfiddle's echo.
Правильный код [правильный код][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 ) ) })
Для конечных точек, принимающих полезную нагрузку в формате JSON, оригинальный код верен.
Я думаю, что ваш вопрос jsfiddle может обрабатывать формы-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
, вместо того чтобы набирать ее, как я сделал выше, является использование библиотек. Например, функцию stringify
из пакетов query-string
или qs
. Таким образом, если использовать эту функцию, то это будет выглядеть следующим образом:
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}
});
Потратив некоторое время на реинжиниринг jsFiddle, попытавшись сгенерировать полезную нагрузку - эффект есть.
Пожалуйста, обратите внимание на строку return response.json();
, где response не является ответом - это обещание.
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Я создал тонкую оболочку вокруг выборки() с множеством улучшений, если вы используете чисто в JSON API-интерфейс REST:
// 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);
});
Чтобы использовать его, у вас есть переменная АПИ и 4 методов:
api.get('/todo').then(all => { /* ... */ });
И в асинхронный
функция:
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');
});
Была такая же проблема - не "тело" был отправлен от клиента к серверу.
Заголовок добавляя тип содержимого
решена она для меня:
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 => {
...
})
Это связано с контент-тип. Как вы могли заметить из других дискуссий и ответов на этот вопрос некоторые люди были в состоянии решить это путем установки
тип контента: 'приложение/JSON'`. К сожалению, в моем случае это не'т работу, моей просьбе пост был по-прежнему пуст на стороне сервера.
Однако, если попробовать с помощью jQuery'ы $.должность (должность) и он's работает, причина, вероятно, потому, что в jQuery, используя
тип контента: 'х-www-формы-urlencoded'вместо
приложение/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'}
})
Верхний ответ Не't работа для 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);
});
}
Это может быть полезно кому-то:
У меня был вопрос о том, что виде FormData не был отправлен по моей просьбе
В моем случае это была комбинация из следующих заголовков, которые также были причиной проблемы и неправильное содержание-типа.
Так что я посылаю эти два заголовка с запросом, и это было'т отправка в виде FormData, когда я убрал заголовки, которые работали.
"Какая я х-прототип-версия&; : "и 1.6.1 и", и"Х-просил-с" : на "запрос"и
Также как и другие ответы свидетельствуют, что контент-тип заголовка должен быть правильным.
На мой запрос правильный контент-тип заголовка:
"По материалам-типа" и: "и применение/х-www-формы-urlencoded; кодировка=кодировка UTF-8"и
Подведем итог, если ваш FormData-это не привязываясь к запросу, то это может потенциально быть свой заголовок. Попробуйте перенести ваши заголовки до минимума, а затем попробуйте добавлять их по одному, чтобы увидеть, если ваша проблема rsolved.
Если ваши полезные данные JSON содержит массивы и вложенные объекты, я хотел бы использовать URLSearchParams
и jQuery'ы параметра()` метод.
fetch('/somewhere', {
method: 'POST',
body: new URLSearchParams($.param(payload))
})
На ваш сервер, это будет выглядеть как стандартный HTML в <форма>
быть `пост объед.
Я думаю, что мы не'т необходимость парсить 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'