So überprüfen Sie, ob die Antwort eines Abrufs ein JSON-Objekt in Javascript ist

94

Ich verwende Fetch Polyfill, um einen JSON oder Text von einer URL abzurufen. Ich möchte wissen, wie ich überprüfen kann, ob die Antwort ein JSON-Objekt oder nur Text ist

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

Antworten:

160

Sie können nach der content-typeAntwort suchen , wie in diesem MDN-Beispiel gezeigt :

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

Wenn Sie absolut sicher sein müssen, dass der Inhalt gültiges JSON ist (und den Headern nicht vertrauen), können Sie die Antwort jederzeit einfach als akzeptieren textund selbst analysieren:

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

Wenn Sie verwenden async/await, können Sie es linearer schreiben:

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
quelle
1
Über dieselbe Strategie können Sie auch response.json in Kombination mit catch verwenden. Wenn Sie einen Fehler feststellen, bedeutet dies, dass es sich nicht um JSON handelt. Wäre das nicht eine idiomatischere Art, damit umzugehen (anstatt response.json fallen zu lassen)?
Wouter Ronteltap
3
@WouterRonteltap: Darfst du nicht nur das eine oder andere machen? Es scheint, als würde ich mich daran erinnern, dass Sie nur einen Schuss auf response.anything () bekommen. Wenn ja, ist JSON Text, aber Text ist nicht unbedingt JSON. Daher müssen Sie zuerst die sichere Sache tun, nämlich .text (). Wenn Sie zuerst .json () ausführen und dies fehlschlägt, haben Sie wahrscheinlich nicht die Möglichkeit, auch .text () auszuführen. Wenn ich falsch liege, zeige es mir bitte anders.
Lonnie Best
2
Meiner Meinung nach können Sie den Headern nicht vertrauen (obwohl Sie sollten, aber manchmal können Sie den Server auf der anderen Seite einfach nicht steuern). Es ist also großartig, dass Sie in Ihrer Antwort auch Try-Catch erwähnen.
Jacob
2
Ja, @Lonnie Best ist in dieser Hinsicht völlig korrekt. Wenn Sie .json () aufrufen und eine Ausnahme auslösen (da die Antwort nicht json ist), erhalten Sie die Ausnahme "Body wurde bereits verbraucht", wenn Sie anschließend .text () aufrufen
Andy
1

Verwenden Sie einen JSON-Parser wie 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
quelle