首页 文章

获取:POST json数据

提问于
浏览
328

我正在尝试使用fetch发布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's json echo我'd expect to see the object I'已发送( {a: 1, b: 2} )时,但这不会发生 - chrome devtools没有't even show the JSON as part of the request, which means that it'未被发送 .

11 回答

  • 8

    我认为您的问题是 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));
    
  • 0

    有同样的问题 - 没有 body 从客户端发送到服务器 .

    添加 Content-Type Headers 为我解决了它:

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

    从搜索引擎开始,我最后就非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'
    });
    

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

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

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

    它可能对某人有用:

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

    在我的情况下,它是以下 Headers 的组合,也导致问题和错误的内容类型 .

    所以我发送这两个标头的请求,当我删除有效的标头时它没有发送formdata .

    “X-Prototype-Version”:“1.6.1”,
    “X-Requested-With”:“XMLHttpRequest”

    此外,其他答案表明Content-Type标头需要正确 .

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

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

    如果您的formdata没有附加到请求那么底线,那么它可能是您的 Headers . 尝试将标头降至最低,然后尝试逐个添加标头,以查看问题是否已解决 .

  • 7

    我认为,我们不需要将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文件作为正文,只需发送一个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 -v -X POST -H 'Content-type: application/x-www-form-urlencoded' -d '@data.txt' '/echo/form'
    
  • 31

    最佳答案不适用于PHP7,因为它有错误的编码,但我可以用其他答案找出正确的编码 . 此代码还会发送身份验证Cookie,您在处理时可能需要这些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);
        });
    }
    
  • 277

    花了一些时间后,逆向工程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

  • -1

    如果您使用的是纯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);
    });
    

    要使用它,您有变量 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');
    });
    
  • 2

    如果你的JSON有效负载包含数组和嵌套对象,我会使用 URLSearchParams 和jQuery的 param() 方法 .

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

    对于您的服务器,这看起来像是一个标准的HTML <form>POST 编辑 .

  • 14

    使用ES2017 async/await support,这是 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);
    })();
    

    可以't use ES2017? See @vp_art' s answer using promises

    然而,问题是要求 a long since fixed chrome bug. 引起的问题
    原始答案如下 .

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

    This is the real issue here ,它是bug with chrome devtools,已在Chrome 46中修复 .

    该代码工作正常 - 它正确地POST了JSON,它只是无法看到 .

    我希望看到我送回的物品

    这不起作用,因为那不是correct format for JSfiddle's echo .

    correct code是:

    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有效负载的 endpoints , the original code is correct

相关问题