Cách kiểm tra xem phản hồi của tìm nạp có phải là đối tượng json trong javascript hay không


94

Tôi đang sử dụng tìm nạp polyfill để truy xuất JSON hoặc văn bản từ URL, tôi muốn biết cách kiểm tra xem phản hồi có phải là đối tượng JSON hay chỉ là văn bản

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

Câu trả lời:


162

Bạn có thể kiểm tra content-typephản hồi, như được hiển thị trong ví dụ MDN này :

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

Nếu bạn cần hoàn toàn chắc chắn rằng nội dung là JSON hợp lệ (và không tin tưởng vào các tiêu đề), bạn luôn có thể chấp nhận phản hồi textvà tự mình phân tích cú pháp:

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 / await

Nếu bạn đang sử dụng async/await, bạn có thể viết nó theo kiểu tuyến tính hơn:

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
Thông qua chiến lược tương tự, bạn có thể chỉ sử dụng response.json kết hợp với catch; nếu bạn bắt lỗi, nó có nghĩa là nó không phải json. Đó sẽ không phải là một cách xử lý điều này thành ngữ hơn (thay vì bỏ qua response.json)?
Wouter Ronteltap

3
@WouterRonteltap: Không phải bạn chỉ được phép làm cái này hay cái khác. Có vẻ như tôi nhớ rằng bạn chỉ nhận được một lần phản hồi tại response.anything (). Nếu vậy, JSON là văn bản, nhưng văn bản không nhất thiết phải là JSON. Do đó, bạn phải làm điều chắc chắn đầu tiên, đó là .text (). Nếu bạn thực hiện .json () trước và nó không thành công, tôi không nghĩ rằng bạn sẽ có cơ hội thực hiện .text (). Nếu tôi sai, xin vui lòng chỉ cho tôi khác.
Lonnie tốt nhất

2
Theo ý kiến ​​của tôi, bạn không thể tin tưởng vào các tiêu đề (mặc dù bạn nên làm như vậy, nhưng đôi khi bạn không thể kiểm soát máy chủ ở phía bên kia). Vì vậy, thật tuyệt khi bạn cũng đề cập đến try-catch trong câu trả lời của mình.
Jacob

2
Vâng, @Lonnie Best hoàn toàn chính xác trong điều này. nếu bạn gọi .json () và nó ném ra một ngoại lệ (vì phản hồi không phải là json), bạn sẽ nhận được ngoại lệ "Nội dung đã được tiêu thụ" nếu sau đó bạn gọi .text ()
Andy

2

Bạn có thể làm điều này một cách rõ ràng với một chức năng trợ giúp:

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

Và sau đó sử dụng nó như thế này:

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

Điều này sẽ tạo ra một lỗi để bạn có thể thực hiện catchnếu muốn.


1

Sử dụng trình phân tích cú pháp JSON như 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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.