[javascript] 가져 오기 : POST JSON 데이터

fetch 사용하여 JSON 객체를 POST하려고합니다 .

내가 이해할 수있는 것에서, 문자열 화 된 객체를 요청의 본문에 첨부해야합니다.

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 echo를 사용하면 보낸 객체 ( {a: 1, b: 2})를 다시 볼 것으로 예상 되지만 이것은 발생하지 않습니다. 크롬 devtools는 JSON을 요청의 일부로 표시하지 않으므로 전송되지 않습니다.



답변

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

ES2017을 사용할 수 없습니까? @ vp_art ‘s 참조약속을 사용하여 답변

그러나이 문제 는 오랫동안 수정 된 크롬 버그로 인한 문제를 묻고 있습니다.
원래 답변은 다음과 같습니다.

크롬 devtools는 요청의 일부로 JSON을 표시하지 않습니다.

이것은 실제 문제 이며 크롬 devtools버그입니다. 이며 Chrome 46에서 수정 된 .

이 코드는 정상적으로 작동합니다 .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 페이로드를 허용하는 엔드 포인트의 경우 원래 코드가 정확합니다.


답변

귀하의 문제는 요청 만 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이 아닌 게시 ​​데이터에 대해이 주제를 찾았으므로 이것을 추가 할 것이라고 생각했습니다.

들어 비 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위와 같이 문자열을 작성하는 대신 문자열 을 작성하는 다른 방법 은 라이브러리를 사용하는 것입니다. 예를 들어 stringifyfrom query-string또는 qs패키지 의 기능 . 따라서 이것을 사용하면 다음과 같습니다.

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


답변

몇 시간을 보낸 후 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


답변

순수 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');
});


답변

와 관련이 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 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 => {
   ...
})