Fetch: POST json डेटा


560

मैं लाने के लिए एक 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 के json इको का उपयोग करते समय मैं आपके द्वारा भेजे गए ऑब्जेक्ट ( {a: 1, b: 2}) को वापस देखने की उम्मीद करूंगा , लेकिन ऐसा नहीं होता है - क्रोम डेवटूल्स भी JSON को अनुरोध के भाग के रूप में नहीं दिखाता है, जिसका अर्थ है कि यह भेजा नहीं जा रहा है।


आप कौन सा ब्राउज़र उपयोग कर रहे हैं?
Krzysztof Safjanowski

@KrzysztofSafjanowski क्रोम 42, जिसका मतलब है कि पूर्ण समर्थन प्राप्त है
रेजर

इस फिडेल jsfiddle.net/abbpbah4/2 की जांच करें कि आप किस डेटा की उम्मीद कर रहे हैं? क्योंकि fiddle.jshell.net /echo/json का अनुरोध प्राप्त करें, खाली वस्तु दिखा रहा है। {}
कौशिक

@ कौशिककिशोर ने अपेक्षित उत्पादन को स्पष्ट करने के लिए संपादन किया। res.json()लौट जाना चाहिए {a: 1, b: 2}
रेजर

1
आप उस jsonसंपत्ति को शामिल करना भूल गए जिसमें वह डेटा है जिसे आप भेजना चाहते हैं। हालाँकि, मुझे bodyसही तरीके से इलाज नहीं किया जा रहा है। इस फिडेल को देखने के लिए कि 5 सेकंड की देरी से छोड़ दिया जाता है। jsfiddle.net/99arsnkg इसके अलावा, जब आप अतिरिक्त हेडर जोड़ने की कोशिश करते हैं, तो उन्हें नजरअंदाज कर दिया जाता है। यह शायद fetch()अपने आप में एक मुद्दा है।
बूमबॉक्स

जवाबों:


597

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 का उत्तर देखें

हालांकि यह सवाल तय क्रोम बग के कारण लंबे समय से एक मुद्दे के लिए पूछ रहा है
मूल उत्तर इस प्रकार है।

क्रोम devtools अनुरोध के हिस्से के रूप में JSON भी नहीं दिखाते हैं

यह यहां वास्तविक मुद्दा है , और क्रोम 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 पेलोड को स्वीकार करने वाले अंतिम बिंदुओं के लिए, मूल कोड सही है


15
रिकॉर्ड के लिए, यह JSON पेलोड पोस्ट नहीं कर रहा है - यह एक फॉर्म पोस्ट ( x-www-form-urlencoded) है जिसका नाम JSON डेटा के साथ फ़ील्ड में है json। तो डेटा दोगुना एन्कोडेड है। स्वच्छ JSON पोस्ट के लिए, नीचे @vp_arth द्वारा उत्तर देखें।
mindplay.dk

1
@ mindplay.dk यह x-www-form-urlencoded पोस्ट नहीं है। फ़ॉर्च API हमेशा फ़ॉर्मडैट ऑब्जेक्ट पर मल्टीपार्ट / फॉर्म-डेटा एन्कोडिंग का उपयोग करता है।
जूकाक

@JukkaP मैं सही है। मेरा मुख्य बिंदु डबल एन्कोडिंग मुद्दा था।
mindplay.dk

2
सामग्री-प्रकार अभी भी पाठ / html है; charset = iso-8859-1 पता नहीं मैं क्या गलत कर रहा हूं ...
KT वर्क्स

3
सुरक्षित पक्ष में रहने के लिए, res.okप्रतिक्रिया कोड किसी प्रकार की त्रुटि होने की स्थिति में पुष्टि करना अच्छा होगा । .catch()अंत में एक खंड होना भी अच्छा होगा। मुझे लगता है कि यह सिर्फ एक नमूना स्निपेट है, लेकिन वास्तविक दुनिया के उपयोग के लिए इन बातों को ध्यान में रखें।
केन लियोन

206

मुझे लगता है कि आपका मुद्दा केवल अनुरोध 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));


6
यह सही समाधान है, अवधि - हर कोई x-www-form-urlencodedबनाम के बारे में मिलाया जा रहा है application/json, या तो उन्हें बेमेल या डबल-रैपिंग जेन्सन को यूआरएल-एन्कोडेड स्ट्रिंग्स में।
mindplay.dk

लेकिन यह jsfiddle के लिए काम नहीं करता है। इसलिए, मुझे यकीन नहीं है कि मैं समझता हूं कि आप क्यों कहेंगे "यह सही समाधान है, अवधि"। क्या jsfiddle के /echoमार्ग को पूरा करने के लिए हर कोई रैपिंग नहीं कर रहा है ?
एडम-बीक

69

खोज इंजन से, मैंने गैर-जोंस के साथ भ्रूण के साथ डेटा पोस्ट करने के लिए इस विषय पर समाप्त किया, इसलिए सोचा कि मैं इसे जोड़ूंगा।

के लिए गैर 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स्ट्रिंग को बनाने का एक वैकल्पिक तरीका , बल्कि इसे टाइप करना जैसा कि मैंने ऊपर किया था, पुस्तकालयों का उपयोग करना है। उदाहरण के लिए या पैकेज stringifyसे फ़ंक्शन । तो इसका उपयोग करके ऐसा लगेगा:query-stringqs

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

2
क्वेरी स्ट्रिंग के लिए बहुत-बहुत धन्यवाद, मैंने JSON.stringify के साथ कई बार कोशिश की, लेकिन अजाक्स प्रतिक्रिया नहीं दे रहा था। लेकिन क्वेरी स्ट्रिंग ने चाल चली। मैंने यह भी पाया कि यह इसलिए था क्योंकि एक स्ट्रिंग बनाने के बजाय बॉडी परेम के लिए जोंस बनाते थे।
डेनिश

1
आपको धन्यवाद! यह सबसे अच्छा जवाब है! मैं कुछ घंटों के लिए कल दीवार को टटोल रहा था, अपने वेब एप्लिकेशन से अपने सर्वर पर फॉर्म डेटा के साथ 'बॉडी' भेजने का रास्ता खोजने की कोशिश कर रहा था ... एक सुझाव: $ npm cors --save स्थापित करें इससे छुटकारा पाने के लिए आवश्यक है " मोड: 'नो-कॉर्स' "फ़िच रिक्वेस्ट में देखें github.com/expressjs/cors
Alexander Cherednichenko

धन्यवाद @AlexanderCherednichenko! और साझा करने के लिए धन्यवाद कि cors नोट एक दिलचस्प है जिसके बारे में मुझे नहीं पता था। :)
Noitidart

1
मेरे दिल की गहराई से धन्यवाद। आपने मेरा समय बचाया और मेरे जीवन को भी दो बार :)
bafsar

1
थंक्स @ बफसर!
Noitidart

42

कुछ समय बिताने के बाद, रिवर्स इंजीनियरिंग 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/ && फ़ायरफ़ॉक्स> 39 && क्रोम + 42


'x-www-form-urlencodedइसके बजाय क्यों application/json? क्या फर्क पड़ता है?
जुआन पिकाडो

@JuanPicado - 2 साल पहले jsfiddle रिवर्स इंजीनियरिंग के बाद यह केवल एक ही विकल्प था कि यह काम कर सके। बेशक application/jsonसही रूप है और यह अब काम करता है। अच्छी नज़र के लिए धन्यवाद
:)

YW। जिज्ञासु विस्तार से, यह मेरे लिए पुराने तरीके से काम करता है fetch( stackoverflow.com/questions/41984893/… ) के बजाय application/json। शायद आपको पता हो कि क्यों ...
जुआन पिकाडो 10

6
Content-Typeहै application/json, लेकिन अपने वास्तविक bodyरूप से प्रदर्शित करना x-www-form-urlencoded- मुझे नहीं लगता कि यह काम करना चाहिए करते हैं? यदि यह काम करता है, तो आपका सर्वर बहुत क्षमाशील होना चाहिए। नीचे @vp_arth का उत्तर सही प्रतीत होता है।
mindplay.dk

18

यदि आपने शुद्ध विशुद्ध रूप से REST API का उपयोग कर रहे हैं, तो मैंने कई सुधारों के साथ एक पतला रैपर बनाया है।

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

मुझे लगता है कि आपके पास तर्क का एक अलग सेट है Object.assign? होना चाहिए Object.assign({}, api.headers, headers)क्योंकि आप headersसामान्य के हैश में कस्टम जोड़ना नहीं रखना चाहते हैं api.headers। सही?
मोबिजिटल

@Mobigital पूरी तरह से सही है, मैं उस बारीकियों के बारे में पहले नहीं जानता था, लेकिन अब मैं इसे करने का एकमात्र तरीका है
फ्रांसिस्को प्रेसेंसिया

11

इससे संबंधित है 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'}
})

1
मेरे बैकएंड देव ने एपीआई को पीएचपी के साथ बनाया था, वह डेटा को क्वेरी स्ट्रिंग की तरह होने की उम्मीद कर रहा था, न कि एक जेंस ऑब्जेक्ट। इसने सर्वर की ओर से खाली प्रतिक्रिया को हल किया।
eballeste

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

7

शीर्ष उत्तर PHP7 के लिए काम नहीं करता है, क्योंकि इसमें गलत एन्कोडिंग है, लेकिन मैं अन्य उत्तरों के साथ सही एन्कोडिंग का पता लगा सकता हूं। यह कोड प्रमाणीकरण कुकीज़ भी भेजता है, जो कि आप संभवत: उदाहरण के लिए जैसे 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);
    });
}

3

यह किसी के लिए उपयोगी हो सकता है:

मुझे यह समस्या हो रही थी कि मेरे अनुरोध के लिए फॉर्मडाटा नहीं भेजा जा रहा था

मेरे मामले में यह निम्नलिखित शीर्ष लेखों का एक संयोजन था जो समस्या और गलत सामग्री-प्रकार का कारण बन रहे थे।

इसलिए मैं अनुरोध के साथ इन दो हेडर को भेज रहा था और जब मैंने काम किया हेडर को हटाया तो यह फॉर्मडेटा नहीं भेज रहा था।

"X-Prototype-Version" : "1.6.1",
"X-Requested-With" : "XMLHttpRequest"

साथ ही अन्य उत्तरों से पता चलता है कि कंटेंट-टाइप हेडर को सही होना चाहिए।

मेरे अनुरोध के लिए सही सामग्री-प्रकार हेडर था:

"सामग्री प्रकार": "आवेदन / x-www फार्म-urlencoded; charset = UTF-8"

इसलिए नीचे की रेखा यदि आपका फॉर्मडेटा अनुरोध में संलग्न नहीं किया जा रहा है तो यह संभावित रूप से आपके हेडर हो सकते हैं। अपने हेडर को कम से कम लाने की कोशिश करें और फिर उन्हें एक-एक करके जोड़ने का प्रयास करें कि आपकी समस्या का समाधान हो रहा है या नहीं।


3

मुझे लगता है कि, हम की जरूरत है एक स्ट्रिंग में 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'

दूरस्थ सेवा के मामले में एक जोंस फाइल को शरीर के रूप में स्वीकार नहीं करना चाहिए, बस एक डेटा भेजें:

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'

2
यह स्पष्ट रूप से गलत है। इसका सर्वर साइड से कोई लेना-देना नहीं है, चाहे आपको अपना जौंस सख्त करने की जरूरत हो या न हो। यह वही है जो आपकी curlआज्ञा निहित रूप से कर रही है! यदि आप उन्हें पास करने से पहले अपनी वस्तुओं को सख्त नहीं करते हैं, bodyतो आप "[object Object]"अपने अनुरोध के मुख्य भाग के रूप में भेज देंगे । देव टूल्स में एक साधारण परीक्षण आपको दिखाएगा। इसे खोलें और इस टैब को छोड़े बिना इसे आज़माएं:a = new FormData(); a.append("foo","bar"); fetch("/foo/bar", { method: 'POST', body: {}, headers: { 'Content-type': 'application/json' } })
ऑलिगॉफ्रेन

2

यदि आपके JSON पेलोड में एरेज़ और नेस्टेड ऑब्जेक्ट हैं, तो मैं उपयोग करूँगा URLSearchParams और jQuery की param()विधि।

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

आपके सर्वर करने के लिए, यह एक मानक HTML तरह दिखेगा <form>से किया जा रहा POSTएड।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.