Cara memeriksa apakah respons dari pengambilan adalah objek json di javascript

100

Saya menggunakan fetch polyfill untuk mengambil JSON atau teks dari URL, saya ingin tahu bagaimana cara memeriksa apakah responsnya adalah objek JSON atau hanya teks

fetch(URL, options).then(response => {
   // how to check if response has a body of type json?
   if (response.isJson()) return response.json();
});
Sibelius Seraphini
sumber

Jawaban:

178

Anda dapat memeriksa content-typeresponnya, seperti yang ditunjukkan pada contoh MDN ini :

fetch(myRequest).then(response => {
  const contentType = response.headers.get("content-type");
  if (contentType && contentType.indexOf("application/json") !== -1) {
    return response.json().then(data => {
      // process your JSON data further
    });
  } else {
    return response.text().then(text => {
      // this is text, do something with it
    });
  }
});

Jika Anda perlu benar-benar yakin bahwa kontennya adalah JSON yang valid (dan tidak mempercayai header), Anda selalu dapat menerima respons sebagai textdan menguraikannya sendiri:

fetch(myRequest)
  .then(response => response.text())
  .then(text => {
    try {
        const data = JSON.parse(text);
        // Do your JSON handling here
    } catch(err) {
       // It is text, do you text handling here
    }
  });

Asinkron / tunggu

Jika Anda menggunakan async/await, Anda dapat menuliskannya dengan cara yang lebih linier:

async function myFetch(myRequest) {
  try {
    const reponse = await fetch(myRequest); // Fetch the resource
    const text = await response.text(); // Parse it as text
    const data = JSON.parse(text); // Try to parse it as json
    // Do your JSON handling here
  } catch(err) {
    // This probably means your response is text, do you text handling here
  }
}
nils
sumber
1
Melalui strategi yang sama Anda bisa menggunakan response.json dalam kombinasi dengan catch; jika Anda menemukan kesalahan, itu berarti itu bukan json. Bukankah itu cara yang lebih idiomatis untuk menangani ini (daripada membuang response.json)?
Wouter Ronteltap
3
@WouterRonteltap: Bukankah Anda hanya diizinkan melakukan satu atau yang lain. Sepertinya saya ingat bahwa Anda hanya mendapat satu kesempatan untuk merespons. Apapun (). Jika demikian, JSON adalah teks, tetapi teks belum tentu JSON. Oleh karena itu, Anda harus melakukan hal yang pasti terlebih dahulu yaitu .text (). Jika Anda melakukan .json () terlebih dahulu, dan gagal, saya rasa Anda tidak akan mendapatkan kesempatan untuk juga melakukan .text (). Jika saya salah, tolong tunjukkan saya yang berbeda.
Lonnie Best
2
Menurut pendapat saya, Anda tidak dapat mempercayai tajuknya (meskipun Anda harus, tetapi terkadang Anda tidak dapat mengontrol server di sisi lain). Jadi, sangat bagus jika Anda juga menyebutkan coba-tangkap dalam jawaban Anda.
Yakub
2
Ya, @Lonnie Best sepenuhnya benar dalam hal ini. jika Anda memanggil .json () dan memunculkan pengecualian (karena responsnya bukan json), Anda akan mendapatkan pengecualian "Tubuh telah dikonsumsi" jika Anda kemudian memanggil .text ()
Andy
3

Anda dapat melakukan ini dengan bersih menggunakan fungsi helper:

const parseJson = async response => {
  const text = await response.text()
  try{
    const json = JSON.parse(text)
    return json
  } catch(err) {
    throw new Error("Did not receive JSON, instead received: " + text)
  }
}

Dan kemudian gunakan seperti ini:

fetch(URL, options)
.then(parseJson)
.then(result => {
    console.log("My json: ", result)
})

Ini akan menimbulkan kesalahan sehingga Anda dapat catchmelakukannya jika Anda mau.

larskarbo.dll
sumber
1

Gunakan parser JSON seperti JSON.parse:

function IsJsonString(str) {
    try {
        var obj = JSON.parse(str);

         // More strict checking     
         // if (obj && typeof obj === "object") {
         //    return true;
         // }

    } catch (e) {
        return false;
    }
    return true;
}
Rakesh Soni
sumber