获取:POST json数据

时间:2015-04-21 14:54:41

标签: javascript json fetch-api

我正在尝试使用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时,我希望看到我发送的对象({a: 1, b: 2}),但这不会发生 - chrome devtools甚至不显示JSON作为请求,这意味着它没有被发送。

16 个答案:

答案 0 :(得分:379)

使用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);
})();

无法使用ES2017?请参阅@ vp_art的answer using promises

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

  

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

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

答案 1 :(得分:162)

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




答案 2 :(得分:39)

在搜索引擎中,我最后讨论了非json发布数据的主题,因此我想加上这个。

对于 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字符串的另一种方法是使用库,而不是像上面那样输入它。例如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}
});

答案 3 :(得分:32)

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

答案 4 :(得分:16)

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

答案 5 :(得分:10)

有同样的问题 - 没有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 => {
   ...
})

答案 6 :(得分:9)

这与ScaleToFit有关。您可能已经注意到其他讨论和这个问题的答案,有些人可以通过设置Content-Type来解决它。不幸的是,在我的情况下它不起作用,我的POST请求在服务器端仍然是空的。

但是,如果您尝试使用jQuery的Content-Type: 'application/json'并且它正在运行,原因可能是因为jQuery使用$.post()而不是Content-Type: 'x-www-form-urlencoded'

application/json

答案 7 :(得分:3)

对某些人可能有用:

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

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

所以我发送了这两个带有请求的标头,当我删除有效的标头时它没有发送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未附加到请求,那么底线可能是您的标题。尝试将标题降至最低,然后尝试逐个添加标题,以查看问题是否已解决。

答案 8 :(得分:3)

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

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

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

答案 9 :(得分:2)

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

我使用 jsonplaceholder fake API 来演示:

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

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

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

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

使用 Promise 的 GET 请求:

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

使用 Promise 的 POST 请求:

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

使用 Axios 的 GET 请求:

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

使用 Axios 的 POST 请求:

{{1}}

答案 10 :(得分:1)

最佳答案不适用于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);
    });
}

答案 11 :(得分:1)

您可以使用fill-fetch,它是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'
    }
});

答案 12 :(得分:1)

使用 await/async 可以做得更好。

http请求的参数:

const outputFolder = "./images/webp";
const produceWebP = async () => {
    // Load ESM modules using import(),
    // it returns a Promise which resolves to
    // default export as 'default' and other named exports.
    // In this case we need default export.
    const imagemin = (await import("imagemin")).default;
    const webp = (await import("imagemin-webp")).default;
    await imagemin(["images/*.png"], {
        destination: outputFolder,
        plugins: [
            webp({
                lossless: true,
            }),
        ],
    });
    console.log("PNGs processed");
    await imagemin(["images/*.{jpg,jpeg}"], {
        destination: outputFolder,
        plugins: [
            webp({
                quality: 65,
            }),
        ],
    });
    console.log("JPGs and JPEGs processed");
};
produceWebP();

使用干净的 async/await 语法:

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

使用老式的 fetch().then().then():

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

答案 13 :(得分: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((response) => {if(response.ok){alert("the call works ok")}})
.catch (function (error) {
    console.log('Request failed', error);
});    

答案 14 :(得分:0)

我的简单目标是js object ->-> php $_POST

Object.defineProperties(FormData.prototype, { // extend FormData for direct use of js objects
    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 )

答案 15 :(得分:-1)

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

@Entity
@Table(name = "tier_two_question")
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(value = { "createdAt", "updatedAt" }, allowGetters = true)
public class TierTwoQuestion implements Serializable {
    /**
     *
     */
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotBlank
    @Column(unique=true)
    private String question;

    @ManyToOne
    @JoinColumn(name = "maintenanceId", nullable = false)
    private MaintenanceType maintenanceType;

    @OneToMany(mappedBy = "tierTwoQuestion", cascade = CascadeType.ALL)
    private Set<TierThreeQuestion> tierThreeQuestion;

    @Column(nullable = false, updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    @CreatedDate
    private Date createdAt;

    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    @LastModifiedDate
    private Date updatedAt;

    public TierTwoQuestion() {
    }


    public TierTwoQuestion(Long id) {
        super();
        this.id = id;
        this.question = question;
    }


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getQuestion() {
        return question;
    }

    public void setQuestion(String question) {
        this.question = question;
    }

    public Date getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }

    public Date getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(Date updatedAt) {
        this.updatedAt = updatedAt;
    }

    // public MaintenanceType getMaintenanceType() {
    // return maintenanceType;
    // }

    public void setMaintenanceType(MaintenanceType maintenanceType) {
        this.maintenanceType = maintenanceType;
    }

    public Set<TierThreeQuestion> getTierThreeQuestion() {
        return tierThreeQuestion;
    }

    public void setTierThreeQuestion(Set<TierThreeQuestion> tierThreeQuestion) {
        this.tierThreeQuestion = tierThreeQuestion;
    }

}

如卷曲请求

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

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

curl -v -X POST -H 'Content-Type: application/json' -d '@data.json' '/echo/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
});