提取:POST json数据

本文探讨了如何使用fetch API正确地POST JSON对象。作者遇到Chrome开发者工具未显示JSON请求体的问题,但实际上是由于已修复的Chrome bug。解决方案是设置正确的请求头和使用JSON.stringify()。还提到了对于非JSON数据的POST请求的处理方式。
摘要由CSDN通过智能技术生成

本文翻译自:Fetch: POST json data

I'm trying to POST a JSON object using fetch . 我正在尝试使用fetch发布 JSON对象。

From what I can understand, I need to attach a stringified object to the body of the request, eg: 据我了解,我需要将一个字符串化的对象附加到请求的主体,例如:

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

When using jsfiddle's json echo I'd expect to see the object I've sent ( {a: 1, b: 2} ) back, but this does not happen - chrome devtools doesn't even show the JSON as part of the request, which means that it's not being sent. 当使用jsfiddle的json回显时,我希望能看到已发送的对象( {a: 1, b: 2} ),但这不会发生-chrome devtools甚至不显示JSON作为请求的一部分,这表示它没有被发送。


#1楼

参考:https://stackoom.com/question/20w2n/提取-POST-json数据


#2楼

After spending some times, reverse engineering jsFiddle, trying to generate payload - there is an effect. 花了一些时间后,对jsFiddle进行反向工程,尝试生成有效负载-会产生效果。

Please take eye (care) on line return response.json(); 请注意行return response.json(); where response is not a response - it is promise. 回应不是回应,而是承诺。

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 jsFiddle: http : //jsfiddle.net/egxt6cpz/46/ && Firefox> 39 && Chrome> 42


#3楼

With ES2017 async/await support , this is how to POST a JSON payload: 随着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); })(); 

Can't use ES2017? 无法使用ES2017? See @vp_art's answer using promises 参见@vp_art 使用诺言答案

The question however is asking for an issue caused by a long since fixed chrome bug. 但是,问题是由很久以来修复的chrome bug引起的
Original answer follows. 原始答案如下。

chrome devtools doesn't even show the JSON as part of the request chrome devtools甚至没有在请求中显示JSON

This is the real issue here , and it's a bug with chrome devtools , fixed in Chrome 46. 这是真正的问题这是 Chrome 46中修复的chrome devtools错误

That code works fine - it is POSTing the JSON correctly, it just cannot be seen. 该代码可以正常工作-它正确地发布了JSON,只是看不到。

I'd expect to see the object I've sent back 我希望看到我寄回的物品

that's not working because that is not the correct format for JSfiddle's echo . 那是行不通的,因为那不是JSfiddle的echo正确格式

The correct code is: 正确的代码是:

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

For endpoints accepting JSON payloads, the original code is correct 对于接受JSON有效负载的端点, 原始代码是正确的


#4楼

From search engines, I ended up on this topic for non-json posting data with fetch, so thought I would add this. 在搜索引擎上,我最终讨论了通过fetch进行非json发布数据的问题,因此我想添加此内容。

For non-json you don't have to use form data. 对于非json,您不必使用表单数据。 You can simply set the Content-Type header to application/x-www-form-urlencoded and use a string: 您可以简单地将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'
});

An alternative way to build that body string, rather then typing it out as I did above, is to use libraries. 构建该body字符串的另一种方法是使用库,而不是像我上面那样键入它。 For instance the stringify function from query-string or qs packages. 例如,来自query-stringqs包的stringify函数。 So using this it would look like: 因此,使用它看起来像:

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

#5楼

I think your issue is jsfiddle can process form-urlencoded request only. 我认为您的问题是jsfiddle只能处理form-urlencoded请求。

But correct way to make json request is pass correct json as a body: 但是发出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)); 


#6楼

I have created a thin wrapper around fetch() with many improvements if you are using a purely json REST API: 如果您使用的是纯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);
});

To use it you have the variable api and 4 methods: 要使用它,您需要使用变量api和4种方法:

api.get('/todo').then(all => { /* ... */ });

And within an async function: async函数中:

const all = await api.get('/todo');
// ...

Example with jQuery: 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');
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值