Analysieren von JSON aus XmlHttpRequest.responseJSON

99

Ich versuche, eine etwas JSON-Antwort in Javascript zu analysieren.

Ich erhalte den JSON über XmlHttpRequest.

var req = new XMLHttpRequest;  
req.overrideMimeType("application/json");  
req.open('GET', BITLY_CREATE_API + encodeURIComponent(url)
          + BITLY_API_LOGIN, true);  
var target = this;  
req.onload  = function() {target.parseJSON(req, url)};  
req.send(null);

parseJSON: function(req, url) {  
if (req.status == 200) {  
    var jsonResponse = req.responseJSON;  
    var bitlyUrl = jsonResponse.results[url].shortUrl;  
}

Ich mache das in einem Firefox-Addon. Wenn ich starte, erhalte ich den Fehler "jsonResponse is undefined" für die Zeile var bitlyUrl = jsonResponse.results[url].shortUrl;. Mache ich hier etwas falsch, wenn ich JSON analysiere? Oder was ist los mit diesem Code?

Chanux
quelle

Antworten:

227

Neue Wege I: fetch

TL; DR Ich würde diesen Weg empfehlen, solange Sie keine synchronen Anfragen senden oder alte Browser unterstützen müssen.

Solange Ihre Anfrage asynchron ist, können Sie die Fetch-API verwenden , um HTTP-Anfragen zu senden. Die Abruf-API arbeitet mit Versprechungen . Dies ist eine gute Möglichkeit, asynchrone Workflows in JavaScript zu verarbeiten. Mit diesem Ansatz fetch()senden Sie eine Anfrage und ResponseBody.json()analysieren die Antwort:

fetch(url)
  .then(function(response) {
    return response.json();
  })
  .then(function(jsonResponse) {
    // do something with jsonResponse
  });

Kompatibilität: Die Fetch-API wird von IE11 sowie Edge 12 und 13 nicht unterstützt. Es gibt jedoch Polyfills .

Neue Wege II: responseType

Wie Londeren in seiner Antwort geschrieben hat , können Sie mit neueren Browsern die responseTypeEigenschaft verwenden, um das erwartete Format der Antwort zu definieren. Auf die analysierten Antwortdaten kann dann über die responseEigenschaft zugegriffen werden :

var req = new XMLHttpRequest();
req.responseType = 'json';
req.open('GET', url, true);
req.onload  = function() {
   var jsonResponse = req.response;
   // do something with jsonResponse
};
req.send(null);

Kompatibilität: responseType = 'json'wird von IE11 nicht unterstützt.

Der klassische Weg

Die Standard-XMLHttpRequest hat keine responseJSONEigenschaft, nur responseTextund responseXML. Solange bitly wirklich mit etwas JSON auf Ihre Anfrage antwortet, responseTextsollte der JSON-Code als Text enthalten sein. Alles, was Sie tun müssen, ist ihn zu analysieren mit JSON.parse():

var req = new XMLHttpRequest();
req.overrideMimeType("application/json");
req.open('GET', url, true);
req.onload  = function() {
   var jsonResponse = JSON.parse(req.responseText);
   // do something with jsonResponse
};
req.send(null);

Kompatibilität: Dieser Ansatz sollte mit jedem Browser funktionieren, der XMLHttpRequestund unterstützt JSON.

JSONHttpRequest

Wenn Sie es vorziehen responseJSON, eine leichtere Lösung als JQuery zu verwenden, sollten Sie sich meine JSONHttpRequest ansehen. Es funktioniert genau wie eine normale XMLHttpRequest, stellt jedoch auch die responseJSONEigenschaft bereit . Alles, was Sie in Ihrem Code ändern müssen, wäre die erste Zeile:

var req = new JSONHttpRequest();

JSONHttpRequest bietet auch Funktionen zum einfachen Senden von JavaScript-Objekten als JSON. Weitere Details und den Code finden Sie hier: http://pixelsvsbytes.com/2011/12/teach-your-xmlhttprequest-some-json/ .

Vollständige Offenlegung: Ich bin der Eigentümer von Pixels | Bytes. Ich denke, mein Skript ist eine gute Lösung für das Problem, deshalb habe ich es hier gepostet. Bitte hinterlassen Sie einen Kommentar, wenn ich den Link entfernen soll.

Torben
quelle
5
+1; IMO war dies die eigentliche Antwort auf die Frage - keine jQuery, einfach nur alte Vanille XMLHttpRequest; genau darum ging es bei der Frage.
Fergus In London
Es gibt einen s a jquery version too. If you are getting crossbrowser issueVersuch, normalerweise behandeln Frameworks diese Probleme besser: api.jquery.com/jquery.parsejson
sagits
1
Vier Jahre später und das hilft immer noch den Menschen. :) Das Verlinken auf den Blog ist in Ordnung, IMO, da es wirklich die vollständige Antwort auf die Frage mit Beispielcode und einem Download ist. Danke dir!
user1094821
"Neue Bibliothek verwenden" ist nicht so hilfreich, wie man denkt.
Grunion Shaftoe
@GrunionShaftoe Könnten Sie bitte erklären, was bedeutet? Ich schlage nicht vor, eine neue Bibliothek zu verwenden. Meine empfohlene Lösung fetchist Standard-JavaScript.
Torben
25

Sie können einfach einstellen xhr.responseType = 'json';

const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1');
xhr.responseType = 'json';
xhr.onload = function(e) {
  if (this.status == 200) {
    console.log('response', this.response); // JSON response  
  }
};
xhr.send();
  

Dokumentation für responseType

Londeren
quelle
Hier gibt es eine große Einschränkung: Weder der IE noch aktuelle Versionen von Edge unterstützen dies (möglicherweise wird Edge dies nach dem Übergang zu Chromium endlich
tun
3

Hinweis: Ich habe dies nur in Chrome getestet.

Es fügt der XMLHttpRequest eine Prototypfunktion hinzu. XHR2 ,

in XHR 1 wahrscheinlich brauchen Sie nur zu ersetzen this.responsemitthis.responseText

Object.defineProperty(XMLHttpRequest.prototype,'responseJSON',{value:function(){
 return JSON.parse(this.response);
},writable:false,enumerable:false});

um den json in xhr2 zurückzugeben

xhr.onload=function(){
 console.log(this.responseJSON());
}

BEARBEITEN

Wenn Sie XHR mit arraybufferoder anderen Antworttypen verwenden möchten , müssen Sie überprüfen, ob die Antwort a ist string.

In jedem Fall müssen Sie weitere Überprüfungen hinzufügen, z. B. wenn der JSON nicht analysiert werden kann.

Object.defineProperty(XMLHttpRequest.prototype,'responseJSON',{value:function(){
 return (typeof this.response==='string'?JSON.parse(this.response):this.response);
},writable:false,enumerable:false});
cocco
quelle
2
Ich würde einen Getter anstelle eines Funktionsattributs definieren, wenn ich Sie wäre. Ersetzen Sie einfach valuemit getin das Objekt übergeben Object.defineProperty, und Sie verwenden können , responseJSONwie Sie jede andere Reaktionsvariable.
wizzwizz4
1

Ich denke, Sie müssen jQuery einschließen, um zu verwenden responseJSON.

Ohne jQuery könnten Sie es mit responseText versuchen und es wie versuchen eval("("+req.responseText+")");

UPDATE : Bitte lesen Sie den Kommentar zu eval, Sie können mit eval testen, aber nicht in der Arbeitserweiterung verwenden.

ODER

benutze json_parse : es wird nicht benutzteval

SIE
quelle
5
Versuchen Sie für ein Firefox-Addon, das mit Chrome-Privilegien ausgeführt wird, nichts zu bewerten, was Sie von einer externen Quelle erhalten. Verwenden Sie stattdessen JSON.parse (zumindest in FF 3.5 und höher).
Ben Combee
1

Verwenden Sie nsIJSON, wenn dies für eine FF-Erweiterung gilt:

var req = new XMLHttpRequest;
req.overrideMimeType("application/json");
req.open('GET', BITLY_CREATE_API + encodeURIComponent(url) + BITLY_API_LOGIN, true);
var target = this;
req.onload = function() {target.parseJSON(req, url)};
req.send(null);

parseJSON: function(req, url) {
if (req.status == 200) {
  var jsonResponse = Components.classes["@mozilla.org/dom/json;1"]
      .createInstance(Components.interfaces.nsIJSON.decode(req.responseText);
  var bitlyUrl = jsonResponse.results[url].shortUrl;
}

Verwenden Sie für eine Webseite einfach JSON.parseanstelle vonComponents.classes["@mozilla.org/dom/json;1"].createInstance(Components.interfaces.nsIJSON.decode

erikvold
quelle