获取:POST JSON数据

我正在尝试使用获取发布一个JSON对象。

根据我的理解,我需要将一个字符串对象附加到请求的主体,例如:

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的JSON回声时,我希望看到我发送的对象({a: 1, b: 2}),但这并没有发生——chrome devols甚至没有将JSON显示为请求的一部分,这意味着它没有被发送。

1416688 次浏览

花了一些时间后,逆向工程jsFiddle,试图生成有效载荷-有效果。

请注意第0行,其中响应不是响应-而是承诺。

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

使用ES2017#0支持,这是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使用Promise回答

然而,问题是问一个由长期以来固定的Chromebug。引起的问题
原答案如下

chrome devols甚至没有将JSON显示为请求的一部分

这才是真正的问题所在,它是bugchrome devols,固定在Chrome46。

这段代码工作得很好——它正确地发布了JSON,只是看不见。

我想看看我送回来的东西

这不起作用,因为这不是JSfiddle回声的正确格式

正确的代码是:

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有效负载的端点,原始代码是正确的

从搜索引擎,我结束了这个主题的非json发布数据与获取,所以我想我会添加这个。

对于非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 workbody: 'foo=bar&blah=1'});

构建body字符串的另一种方法,而不是像我上面那样输入它,是使用库。例如来自query-stringqs包的stringify函数。所以使用它看起来像:

import queryString from 'query-string'; // import the queryString class
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 workbody: queryString.stringify({for:'bar', blah:1}) //use the stringify object of the queryString class});

我认为你的问题是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 REST API,我已经创建了一个围绕get()的薄包装器,并进行了许多改进:

// Small library to improve on fetch() usageconst api = function(method, url, data, headers = {}){return fetch(url, {method: method.toUpperCase(),body: JSON.stringify(data),  // send it as stringified jsoncredentials: api.credentials,  // to keep the session on the requestheaders: Object.assign({}, api.headers, headers)  // extend the headers}).then(res => res.ok ? res.json() : Promise.reject(res));};
// Defaults that can be globally overwrittenapi.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');});

这与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'}})

有同样的问题-没有body从客户端发送到服务器。添加Content-Type标题为我解决了这个问题:

var headers = new Headers();
headers.append('Accept', 'application/json'); // This one is enough for GET requestsheaders.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 => {...})

它可能对某人有用:

我遇到的问题是formdata没有被发送给我的请求

在我的情况下,它是以下标题的组合,也导致了问题和错误的Content-Type。

所以我在请求中发送了这两个标头,当我删除有效的标头时,它没有发送表单数据。

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

同样,其他答案表明Content-Type标头需要正确。

对于我的请求,正确的Content-Type标头是:

"Content-Type":"apps/x-www. form-urlencoded; charset=UTF-8",//请求参数

因此,如果您的表单数据未附加到请求,那么它可能是您的标头。尝试将标头降至最低,然后尝试逐个添加它们,看看您的问题是否得到解决。

我认为,我们不需要将JSON对象解析成字符串,如果远程服务器接受json进入他们的请求,只需运行:

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

例如curl请求

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

如果远程服务不接受json文件作为主体,只需发送一个dataForm:

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请求

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

上面的答案不适用于PHP7,因为它有错误的编码,但我可以用其他答案找出正确的编码。此代码还发送身份验证cookie,您可能在处理例如PHP论坛时需要它:

julia = function(juliacode) {fetch('julia.php', {method: "POST",credentials: "include", // send cookiesheaders: {'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))})

对于您的服务器,这看起来像一个标准的超文本标记语言<form>POSTed。

您可以使用补全,它是fetch的扩展。简单地说,您可以发布数据如下:

import { fill } from 'fill-fetch';
const fetcher = fill();
fetcher.config.timeout = 3000;fetcher.config.maxConcurrence = 10;fetcher.config.baseURL = 'http://www.github.com';
const res = await fetcher.post('/', { a: 1 }, {headers: {'bearer': '1234'}});

您只需要检查响应是否正常,因为调用没有返回任何内容。

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((response) => {if(response.ok){alert("the call works ok")}}).catch (function (error) {console.log('Request failed', error);});
// extend FormData for direct use of js objectsObject.defineProperties(FormData.prototype, {load: {value: function (d) {for (var v in d) {this.append(v, typeof d[v] === 'string' ? d[v] : JSON.stringify(d[v]));}}}})
var F = new FormData;F.load({A:1,B:2});
fetch('url_target?C=3&D=blabla', {method: "POST",body: F}).then( response_handler )

你可以用wait/async做得更好。

超文本传输协议请求参数:

const _url = 'https://jsonplaceholder.typicode.com/posts';let _body = JSON.stringify({title: 'foo',body: 'bar',userId: 1,});const _headers = {'Content-type': 'application/json; charset=UTF-8',};const _options = { method: 'POST', headers: _headers, body: _body };

使用干净的异步/等待语法:

const response = await fetch(_url, _options);if (response.status >= 200 && response.status <= 204) {let data = await response.json();console.log(data);} else {console.log(`something wrong, the server code: ${response.status}`);}

使用老式的获取().然后().然后():

fetch(_url, _options).then((res) => res.json()).then((json) => console.log(json));

2021年答案:以防万一你在这里寻找如何使用async/wait或Promise与axios相比发出GET和POST Fetch api请求。

我正在使用jsonplace e的假API来演示:

获取api GET请求使用async/wait:

         const asyncGetCall = async () => {try {const response = await fetch('https://jsonplaceholder.typicode.com/posts');const data = await response.json();// enter you logic when the fetch is successfulconsole.log(data);} catch(error) {// enter your logic for when there is an error (ex. error toast)console.log(error)}}

asyncGetCall()

使用async/wait获取api POST请求:

    const asyncPostCall = async () => {try {const response = await fetch('https://jsonplaceholder.typicode.com/posts', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({// your expected POST request payload goes heretitle: "My post title",body: "My post content."})});const data = await response.json();// enter you logic when the fetch is successfulconsole.log(data);} catch(error) {// enter your logic for when there is an error (ex. error toast)
console.log(error)}}
asyncPostCall()

使用Promises获取请求:

  fetch('https://jsonplaceholder.typicode.com/posts').then(res => res.json()).then(data => {// enter you logic when the fetch is successfulconsole.log(data)}).catch(error => {// enter your logic for when there is an error (ex. error toast)console.log(error)})

使用Promises发布请求:

fetch('https://jsonplaceholder.typicode.com/posts', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({// your expected POST request payload goes heretitle: "My post title",body: "My post content."})}).then(res => res.json()).then(data => {// enter you logic when the fetch is successfulconsole.log(data)}).catch(error => {// enter your logic for when there is an error (ex. error toast)console.log(error)})

使用Axios获取请求:

        const axiosGetCall = async () => {try {const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts')// enter you logic when the fetch is successfulconsole.log(`data: `, data)           
} catch (error) {// enter your logic for when there is an error (ex. error toast)console.log(`error: `, error)}}    
axiosGetCall()

使用Axios发布请求:

const axiosPostCall = async () => {try {const { data } = await axios.post('https://jsonplaceholder.typicode.com/posts',  {// your expected POST request payload goes heretitle: "My post title",body: "My post content."})// enter you logic when the fetch is successfulconsole.log(`data: `, data)   
} catch (error) {// enter your logic for when there is an error (ex. error toast)console.log(`error: `, error)}}

axiosPostCall()
**//POST a request**

const createTodo = async (todo) =>  {let options = {method: "POST",headers: {"Content-Type":"application/json",},body: JSON.stringify(todo)}let p = await fetch("https://jsonplaceholder.typicode.com/posts", options);let response = await p.json();return response;}
**//GET request**
const getTodo = async (id) => {let response = await fetch('https://jsonplaceholder.typicode.com/posts/' + id);let r = await response.json();return r;}const mainFunc = async () => {let todo = {title: "milan7",body: "dai7",userID: 101}let todor = await createTodo(todo);console.log(todor);console.log(await getTodo(5));}mainFunc()