获取:POST json数据

Raz*_*zor 468 javascript json fetch-api

我正在尝试使用fetch POST一个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) })
Run Code Online (Sandbox Code Playgroud)

当使用jsfiddle的json echo时,我希望看到我发送的对象({a: 1, b: 2}),但这不会发生 - chrome devtools甚至不会将JSON显示为请求的一部分,这意味着它没有被发送.

Raz*_*zor 491

有了ES2017 async/await支持,这就是POSTJSON有效负载的方法:

(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);
})();
Run Code Online (Sandbox Code Playgroud)

不能用ES2017?使用promises查看@ vp_art的答案

然而,问题是要求解决由于长期固定的Chrome错误导致的问题.
原始答案如下.

chrome devtools甚至不会将JSON显示为请求的一部分

这是真正的问题,这是Chrome devtools的一个错误,在Chrome 46中得到修复.

该代码工作正常 - 它正确地POST了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 ) ) })
Run Code Online (Sandbox Code Playgroud)

对于接受JSON有效负载的端点,原始代码是正确的

  • 为了记录,这不是发布JSON有效负载 - 这是一个表单帖子(`x-www-form-urlencoded`),在名为`json`的字段中有一个JSON数据.所以数据是双重编码的.有关干净的JSON帖子,请参阅下面的@vp_arth回答. (14认同)
  • @mindplay.dk 这不是 x-www-form-urlencoded 帖子。Fetch API 总是在 FormData 对象上使用 multipart/form-data 编码。 (2认同)
  • Content-Type仍然是text/html; charset = iso-8859-1不知道我做错了什么... (2认同)
  • 为了安全起见,最好确认一下“ res.ok”,以防响应代码出现某种错误。最后有一个`.catch()`子句也很好。我意识到这只是示例片段,但请牢记这些内容以供实际使用。 (2认同)
  • @Timo:这很大程度上取决于您的服务器;服务器不需要*使用这些字段。但服务器可能会根据“Accept”发出不同的数据,并且可能需要“content-type”来接受 json。最好两者都设置,以避免服务器软件更新时无休止的调试。 (2认同)

vp_*_*rth 181

我认为您的问题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));
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的解决方案,_period_ - 其他人似乎都混淆了`x-www-form-urlencoded` vs`application/json`,要么不匹配,要么在url编码的字符串中包装JSON. (6认同)
  • TNX.asp.net mvc中的正确解决方案. (2认同)
  • 对于那些不熟悉箭头函数的人,您必须在那里 **return** `res.json()` ,以在下一个 `.then()` 调用中获取数据。 (2认同)

Noi*_*art 44

从搜索引擎来看,我最后就非json发布带有fetch的数据发表了这个话题,所以我想加上这个.

对于非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'
});
Run Code Online (Sandbox Code Playgroud)

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

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}
});
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢您查询字符串,我用JSON.stringify尝试了很多次,但是ajax没有返回响应。但是查询字符串可以解决问题。我还发现这是因为fetch为body参数创建json而不是创建字符串。 (2认同)

Krz*_*ski 36

花了一些时间后,逆向工程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);
});
Run Code Online (Sandbox Code Playgroud)

jsFiddle:http://jsfiddle.net/egxt6cpz/46/&& Firefox> 39 && Chrome> 42

  • `Content-Type`是`application/json`,但是你的实际`body`似乎是`x-www-form-urlencoded` - 我不认为这应该有用吗?如果确实有效,那么您的服务器必须非常宽容.@vp_arth的答案似乎是正确的. (6认同)

Fra*_*cia 17

如果您使用纯粹的json REST API,我已经在fetch()周围创建了一个瘦包装器,并进行了许多改进:

// 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);
});
Run Code Online (Sandbox Code Playgroud)

要使用它,你有变量api和4种方法:

api.get('/todo').then(all => { /* ... */ });
Run Code Online (Sandbox Code Playgroud)

并且在一个async功能中:

const all = await api.get('/todo');
// ...
Run Code Online (Sandbox Code Playgroud)

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');
});
Run Code Online (Sandbox Code Playgroud)


Gre*_*een 11

有同样的问题 - 没有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 => {
   ...
})
Run Code Online (Sandbox Code Playgroud)


Mar*_*ind 10

这与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'}
})
Run Code Online (Sandbox Code Playgroud)


Tel*_*nse 9

2021 年答案:以防万一您登陆这里寻找与 axios 相比如何使用 async/await 或 promises 进行 GET 和 POST Fetch api 请求。

我正在使用 jsonplaceholder fake API 来演示:

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

         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 successful
                 console.log(data);
               } catch(error) {
            // enter your logic for when there is an error (ex. error toast)
                  console.log(error)
                 } 
            }


          asyncGetCall()
Run Code Online (Sandbox Code Playgroud)

使用 async/await 获取 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 here
                     title: "My post title",
                     body: "My post content."
                    })
                 });
                 const data = await response.json();
              // enter you logic when the fetch is successful
                 console.log(data);
               } catch(error) {
             // enter your logic for when there is an error (ex. error toast)

                  console.log(error)
                 } 
            }

asyncPostCall()
Run Code Online (Sandbox Code Playgroud)

使用 Promise 的 GET 请求:

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

使用 Promise 的 POST 请求:

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

使用 Axios 的 GET 请求:

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

使用 Axios 的 POST 请求:

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


axiosPostCall()
Run Code Online (Sandbox Code Playgroud)


Mil*_*ura 7

**//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()
Run Code Online (Sandbox Code Playgroud)


lam*_*345 5

最佳答案不适用于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);
    });
}
Run Code Online (Sandbox Code Playgroud)