Mengurai JSON dari XmlHttpRequest.responseJSON

100

Saya mencoba mengurai respons JSON bit.ly di javascript.

Saya mendapatkan JSON melalui 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;  
}

Saya melakukan ini di addon firefox. Ketika saya menjalankan saya mendapatkan kesalahan "jsonResponse tidak ditentukan" untuk baris tersebut var bitlyUrl = jsonResponse.results[url].shortUrl;. Apakah saya melakukan kesalahan dalam mengurai JSON di sini? Atau apa yang salah dengan kode ini?

chanux
sumber

Jawaban:

228

Cara baru saya: fetch

TL; DR Saya akan merekomendasikan cara ini selama Anda tidak perlu mengirim permintaan sinkron atau mendukung browser lama.

Selama permintaan Anda asinkron, Anda dapat menggunakan Fetch API untuk mengirim permintaan HTTP. Fetch API bekerja dengan promise , yang merupakan cara bagus untuk menangani alur kerja asinkron di JavaScript. Dengan pendekatan ini yang Anda gunakan fetch()untuk mengirim permintaan dan ResponseBody.json()mengurai respons:

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

Kompatibilitas: Fetch API tidak didukung oleh IE11 serta Edge 12 & 13. Namun, ada polyfill .

Cara baru II: responseType

Seperti yang ditulis Londeren dalam jawabannya , browser yang lebih baru memungkinkan Anda menggunakan responseTypeproperti untuk menentukan format respons yang diharapkan. Data respons yang diurai kemudian dapat diakses melalui responseproperti:

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

Kompatibilitas: responseType = 'json'tidak didukung oleh IE11.

Cara klasik

XMLHttpRequest standar tidak memiliki responseJSONproperti, hanya responseTextdan responseXML. Selama bitly benar-benar merespons dengan beberapa JSON untuk permintaan Anda, responseTextharus berisi kode JSON sebagai teks, jadi yang harus Anda lakukan hanyalah menguraikannya dengan 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);

Kompatibilitas: Pendekatan ini dapat digunakan dengan browser apa pun yang mendukung XMLHttpRequestdan JSON.

JSONHttpRequest

Jika Anda lebih suka menggunakan responseJSON, tetapi menginginkan solusi yang lebih ringan daripada JQuery, Anda mungkin ingin memeriksa JSONHttpRequest saya. Ia bekerja persis seperti XMLHttpRequest normal, tetapi juga menyediakan responseJSONproperti. Yang harus Anda ubah dalam kode Anda adalah baris pertama:

var req = new JSONHttpRequest();

JSONHttpRequest juga menyediakan fungsionalitas untuk mengirim objek JavaScript dengan mudah sebagai JSON. Detail selengkapnya dan kodenya dapat ditemukan di sini: http://pixelsvsbytes.com/2011/12/teach-your-xmlhttprequest-some-json/ .

Pengungkapan penuh: Saya adalah pemilik Pixels | Bytes. Saya pikir skrip saya adalah solusi yang baik untuk masalah ini, jadi saya mempostingnya di sini. Silakan tinggalkan komentar, jika Anda ingin saya menghapus tautannya.

Torben
sumber
5
+1; IMO ini adalah jawaban sebenarnya untuk pertanyaan itu - tidak ada jQuery hanya vanilla tua biasa XMLHttpRequest; tentang apa pertanyaan itu.
Fergus Di London
Ada yang s a jquery version too. If you are getting crossbrowser issuemencobanya, biasanya framework menangani masalah ini dengan lebih baik: api.jquery.com/jquery.parsejson
sagits
1
Empat tahun kemudian dan ini masih membantu orang. :) Menautkan ke blog itu baik-baik saja IMO, karena ini benar-benar jawaban lengkap untuk pertanyaan dengan kode sampel dan unduhan. Terima kasih!
pengguna1094821
"Gunakan perpustakaan baru" tidak membantu seperti yang dibayangkan.
Grunion Shaftoe
@GrunionShaftoe Bisakah Anda jelaskan, apa maksudnya? Saya tidak menyarankan untuk menggunakan perpustakaan baru. Solusi yang saya rekomendasikan fetchadalah JavaScript standar.
Torben
25

Anda cukup mengatur 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();
  

Dokumentasi untuk responseType

Londeren
sumber
Ada peringatan besar di sini: baik IE, maupun versi Edge saat ini tidak mendukung ini (mungkin Edge akhirnya akan akhirnya setelah beralih ke Chromium)
Machavity
3

Catatan: Saya hanya menguji ini di Chrome.

itu menambahkan fungsi prototipe ke XMLHttpRequest .. XHR2 ,

di XHR 1 Anda mungkin hanya perlu mengganti this.responsedenganthis.responseText

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

untuk mengembalikan json di xhr2

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

EDIT

Jika Anda berencana untuk menggunakan XHR dengan arraybufferatau tipe respons lain, Anda harus memeriksa apakah responsnya adalah a string.

dalam hal apapun Anda harus menambahkan lebih banyak pemeriksaan, misalnya jika tidak dapat mengurai json.

Object.defineProperty(XMLHttpRequest.prototype,'responseJSON',{value:function(){
 return (typeof this.response==='string'?JSON.parse(this.response):this.response);
},writable:false,enumerable:false});
cocco
sumber
2
Saya akan mendefinisikan pengambil alih-alih atribut fungsi jika saya menjadi Anda. Cukup ganti valuedengan getdi objek yang diteruskan Object.defineProperty, dan Anda dapat menggunakan responseJSONseperti yang Anda lakukan pada variabel respons lainnya.
wizzwizz4
1

Saya pikir Anda harus menyertakan jQuery untuk digunakan responseJSON.

Tanpa jQuery, Anda dapat mencoba dengan responseText dan mencoba like eval("("+req.responseText+")");

UPDATE : Silakan baca komentar tentang eval, Anda dapat menguji dengan eval, tetapi jangan menggunakannya dalam ekstensi kerja.

ATAU

gunakan json_parse : tidak digunakaneval

KAMU
sumber
5
Untuk addon Firefox yang berjalan dengan chrome privs, jangan mencoba mengevaluasi apa pun yang Anda dapatkan dari sumber luar. Sebagai gantinya, gunakan JSON.parse (setidaknya di FF 3.5 dan yang lebih baru).
Ben Combee
1

Gunakan nsIJSON jika ini untuk ekstensi 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;
}

Untuk halaman web, gunakan JSON.parsesajaComponents.classes["@mozilla.org/dom/json;1"].createInstance(Components.interfaces.nsIJSON.decode

erikvold
sumber