Analizando JSON desde XMLHttpRequest.Responder


Estoy tratando de analizar un bit.ly Respuesta JSON en javscript.

Obtengo el JSON a través de 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;  
}

Hago esto en un complemento de Firefox. Cuando corro obtengo el error "JsonResponse is undefined" para la línea var bitlyUrl = jsonResponse.results[url].shortUrl;. ¿Estoy haciendo algo malo al analizar JSON aquí? ¿O qué tiene de malo este código?

Author: FruitBreak, 2009-12-29

5 answers

Nuevas formas I: fetch

TL; DR Lo recomendaría de esta manera, siempre y cuando no tenga que enviar solicitudes síncronas o admitir navegadores antiguos.

A mientras su solicitud sea asíncrona, puede usar la API Fetch para enviar solicitudes HTTP. La API fetch funciona con promises , que es una buena manera de manejar flujos de trabajo asíncronos en JavaScript. Con este enfoque se utiliza fetch() para enviar una solicitud y ResponseBody.json() para analizar el respuesta:

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

Compatibilidad: La API Fetch no es compatible con IE11 ni con Edge 12 y 13. Sin embargo, hay polyfills.

Nuevos caminos II: responseType

Como Londeren ha escrito en su respuesta, los navegadores más nuevos le permiten usar la propiedad responseType para definir el formato esperado de la respuesta. Se puede acceder a los datos de respuesta analizados a través de la propiedad 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);

Compatibilidad: responseType = 'json' no es compatible con IE11.

La forma clásica

El estándar XMLHttpRequest no tiene ninguna propiedad responseJSON, solo responseText y responseXML. Mientras bitly realmente responda con algo de JSON a tu solicitud, responseText debería contener el código JSON como texto, así que todo lo que tienes que hacer es analizarlo con 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);

Compatibilidad: Este enfoque debería funcionar con cualquier navegador que soporte XMLHttpRequest y JSON.

JSONHttpRequest

Si prefiere usar responseJSON, pero desea una solución más ligera que jQuery, es posible que desee revisar mi JSONHttpRequest. Funciona exactamente como un XMLHttpRequest normal, pero también proporciona la propiedad responseJSON. Todo lo que tienes que cambiar en tu código sería la primera línea:

var req = new JSONHttpRequest();

JSONHttpRequest también proporciona funcionalidad para enviar fácilmente objetos JavaScript como JSON. Más detalles y el código se pueden encontrar aquí: http://pixelsvsbytes.com/2011/12/teach-your-xmlhttprequest-some-json/.

Revelación completa: Soy el dueño de Pixels / Bytes. Creo que mi guión es una buena solución al problema, así que lo publiqué aquí. Por favor, deja un comentario, si quieres que elimine el enlace.

 171
Author: Torben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-28 12:21:07

Simplemente puede configurar 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();
  

Documentación para responseType

 8
Author: Londeren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-27 08:27:55

Creo que tienes que incluir jQuery para usar responseJSON.

Sin jQuery, puedes probar con responseText y probar como eval("("+req.responseText+")");

ACTUALIZAR : Por favor, lea el comentario sobre eval, puede probar con eval, pero no lo use en la extensión de trabajo.

O

Use json_parse : no usa eval

 2
Author: YOU,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-29 06:39:11

Nota: Solo he probado esto en Chrome.

Añade una función prototype al XMLHttpRequest .. XHR2 ,

En XHR 1 probablemente solo necesite reemplazar this.response por this.responseText

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

Para devolver el json en xhr2

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

EDITAR

Si planea usar XHR con arraybuffer u otros tipos de respuesta, entonces debe verificar si la respuesta es un string.

En cualquier caso, debe agregar más comprobaciones, por ejemplo, si no es capaz de analizar el json.

Object.defineProperty(XMLHttpRequest.prototype,'responseJSON',{value:function(){
 return (typeof this.response==='string'?JSON.parse(this.response):this.response);
},writable:false,enumerable:false});
 2
Author: cocco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-05 02:28:35

Use nsIJSON si esto es para una extensión 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;
}

Para una página web, simplemente use JSON.parse en lugar de Components.classes["@mozilla.org/dom/json;1"].createInstance(Components.interfaces.nsIJSON.decode

 0
Author: erikvold,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-21 06:29:13