วิธีตรวจสอบว่าการตอบสนองของการดึงข้อมูลเป็นวัตถุ json ใน javascript หรือไม่


100

ฉันใช้ fetch polyfill เพื่อดึง JSON หรือข้อความจาก URL ฉันต้องการทราบว่าฉันจะตรวจสอบได้อย่างไรว่าคำตอบนั้นเป็นวัตถุ JSON หรือเป็นข้อความเท่านั้น

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

คำตอบ:


177

คุณสามารถตรวจสอบcontent-typeการตอบสนองดังที่แสดงในตัวอย่าง MDN นี้ :

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

หากคุณต้องการให้แน่ใจอย่างแท้จริงว่าเนื้อหานั้นเป็น JSON ที่ถูกต้อง (และไม่ไว้วางใจส่วนหัว) คุณสามารถยอมรับคำตอบtextและแยกวิเคราะห์ด้วยตัวเองได้เสมอ:

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

Async / รอ

หากคุณกำลังใช้async/awaitคุณสามารถเขียนให้เป็นเส้นตรงมากขึ้น:

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

1
ด้วยกลยุทธ์เดียวกันคุณสามารถใช้ response.json ร่วมกับ catch; หากคุณพบข้อผิดพลาดหมายความว่าไม่ใช่ json นั่นจะเป็นวิธีที่ใช้สำนวนมากกว่าในการจัดการสิ่งนี้หรือไม่ (แทนที่จะทิ้ง response.json)
Wouter Ronteltap

3
@WouterRonteltap: คุณไม่ได้รับอนุญาตให้ทำอย่างใดอย่างหนึ่งเท่านั้น ดูเหมือนว่าฉันจำได้ว่าคุณได้รับการตอบสนองเพียงนัดเดียวทุกอย่าง () ในกรณีนี้ JSON คือข้อความ แต่ข้อความไม่จำเป็นต้องเป็น JSON ดังนั้นคุณต้องทำสิ่งที่แน่นอนก่อนซึ่งก็คือ. text () ถ้าคุณทำ. json () ก่อนและล้มเหลวฉันไม่คิดว่าคุณจะมีโอกาสทำ. text () ถ้าฉันผิดโปรดแสดงความแตกต่าง
Lonnie Best

2
ในความคิดของฉันคุณไม่สามารถเชื่อถือส่วนหัวได้ (แม้ว่าคุณจะควร แต่บางครั้งคุณก็ไม่สามารถควบคุมเซิร์ฟเวอร์ในอีกด้านหนึ่งได้) ดังนั้นจึงเป็นการดีที่คุณจะพูดถึงการลองจับในคำตอบของคุณด้วย
Jacob

2
ใช่ @Lonnie Best ถูกต้องสมบูรณ์ในเรื่องนี้ หากคุณโทร. json () และมันแสดงข้อยกเว้น (เนื่องจากการตอบสนองไม่ใช่ json) คุณจะได้รับข้อยกเว้น "Body has already been Consumed" ถ้าคุณเรียก. text ()
Andy

3

คุณสามารถทำได้อย่างหมดจดด้วยฟังก์ชันตัวช่วย:

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

แล้วใช้มันดังนี้:

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

สิ่งนี้จะทำให้เกิดข้อผิดพลาดดังนั้นคุณสามารถทำได้catchหากต้องการ


1

ใช้ตัวแยกวิเคราะห์ JSON เช่น 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;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.