web-dev-qa-db-fra.com

Analyse de JSON à partir de XmlHttpRequest.responseJSON

J'essaie d'analyser un peu la réponse JSON en javscript.

Je reçois le JSON via 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;  
}

Je le fais dans un addon firefox. Quand j’exécute, l’erreur "jsonResponse est indéfinie" apparaît pour la ligne var bitlyUrl = jsonResponse.results[url].shortUrl;. Est-ce que je fais quelque chose de mal en analysant JSON ici? Ou ce qui ne va pas avec ce code?

79
chanux

Nouvelles manières I: fetch

TL; DR Je le recommanderais si vous n'avez pas à envoyer de message. requêtes synchrones ou supporte les anciens navigateurs.

Tant que votre demande est asynchrone, vous pouvez utiliser le Fetch API pour envoyer des requêtes HTTP. L'API d'extraction fonctionne avec promises , qui est un moyen agréable de gérer les flux de travail asynchrones en JavaScript. Avec cette approche, vous utilisez fetch() pour envoyer une demande et ResponseBody.json() pour analyser la réponse:

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

Compatibilité: L'API Fetch n'est pas pris en charge par IE11 ni par Edge 12 & 13. Cependant, il existe polyfills .

Nouvelles manières II: responseType

Comme Londeren a écrit sa réponse , les nouveaux navigateurs vous permettent d'utiliser la propriété responseType pour définir le format attendu de la réponse. Les données de réponse analysées sont ensuite accessibles via la propriété response:

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

Compatibilité: responseType = 'json' N'est pas supporté par IE11.

La méthode classique

Le XMLHttpRequest standard n'a pas de propriété responseJSON, juste responseText et responseXML. Tant que bitly répond vraiment avec du JSON à votre requête, responseText devrait contenir le code JSON sous forme de texte. Tout ce que vous avez à faire est de l'analyser avec 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);

Compatibilité: cette approche devrait fonctionner avec tout navigateur prenant en charge XMLHttpRequest et JSON.

JSONHttpRequest

Si vous préférez utiliser responseJSON, mais souhaitez une solution plus légère que JQuery, vous pouvez consulter ma requête JSONHttpRequest. Il fonctionne exactement comme un XMLHttpRequest normal, mais fournit également la propriété responseJSON. Tout ce que vous avez à changer dans votre code serait la première ligne:

var req = new JSONHttpRequest();

JSONHttpRequest fournit également une fonctionnalité permettant d'envoyer facilement des objets JavaScript au format JSON. Plus de détails et le code peuvent être trouvés ici: http://pixelsvsbytes.com/2011/12/teach-your-xmlhttprequest-some-json/ .

Divulgation complète: je suis le propriétaire de Pixels | Bytes. Je pense que mon script est une bonne solution au problème, alors je l'ai posté ici. S'il vous plaît laissez un commentaire, si vous voulez que je supprime le lien.

198
Torben

Vous pouvez simplement définir 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();
  

Documentation pour responseType

14
Londeren

Remarque: je n'ai testé cela que dans Chrome.

il ajoute une fonction prototype à XMLHttpRequest .. XHR2,

dans XHR 1 il vous suffit probablement de remplacer this.response avec this.responseText

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

retourner le json en xhr2

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

MODIFIER

Si vous envisagez d'utiliser XHR avec arraybuffer ou d'autres types de réponses, vous devez vérifier si la réponse est un string.

dans tous les cas, vous devez ajouter plus de contrôles, par exemple. si ce n'est pas capable d'analyser le json.

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

Je pense que vous devez inclure jQuery pour utiliser responseJSON.

Sans jQuery, vous pouvez essayer avec responseText et essayer comme eval("("+req.responseText+")");

[~ # ~] update [~ # ~] : Veuillez lire le commentaire concernant eval, vous pouvez tester avec eval, mais don ne l'utilisez pas en extension de travail.

OR

use json_parse : il n'utilise pas eval

2
YOU

Utilisez nsIJSON s'il s'agit d'une extension FF:

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

Pour une page Web, utilisez simplement JSON.parse au lieu de Components.classes["@mozilla.org/dom/json;1"].createInstance(Components.interfaces.nsIJSON.decode

1
erikvold