Phân tích cú pháp JSON từ XmlHttpRequest.responseJSON


99

Tôi đang cố gắng phân tích cú pháp phản hồi JSON bit.ly trong javascript.

Tôi lấy JSON qua 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;  
}

Tôi làm điều này trong một addon firefox. Khi tôi chạy, tôi gặp lỗi "jsonResponse là không xác định" cho dòng var bitlyUrl = jsonResponse.results[url].shortUrl;. Tôi có làm gì sai khi phân tích cú pháp JSON ở đây không? Hoặc có gì sai với mã này?

Câu trả lời:


227

Những cách mới tôi: fetch

TL; DR Tôi khuyên bạn nên làm theo cách này miễn là bạn không phải gửi yêu cầu đồng bộ hoặc hỗ trợ các trình duyệt cũ.

Miễn là yêu cầu của bạn không đồng bộ, bạn có thể sử dụng API Tìm nạp để gửi các yêu cầu HTTP. API tìm nạp hoạt động với các hứa hẹn , đây là một cách hay để xử lý các luồng công việc không đồng bộ trong JavaScript. Với cách tiếp cận này, bạn sử dụng fetch()để gửi yêu cầu và ResponseBody.json()phân tích cú pháp phản hồi:

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

Khả năng tương thích: API Tìm nạp không được hỗ trợ bởi IE11 cũng như Edge 12 & 13. Tuy nhiên, vẫn có các polyfills .

Những cách mới II: responseType

Như Londeren đã viết trong câu trả lời của mình , các trình duyệt mới hơn cho phép bạn sử dụng thuộc responseTypetính để xác định định dạng mong đợi của phản hồi. Dữ liệu phản hồi đã phân tích cú pháp sau đó có thể được truy cập thông qua thuộc responsetính:

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

Khả năng tương thích: responseType = 'json'không được hỗ trợ bởi IE11.

Cách cổ điển

XMLHttpRequest chuẩn không có thuộc responseJSONtính, chỉ responseTextresponseXML. Miễn là thực sự phản hồi một cách bitly với một số JSON cho yêu cầu của bạn, responseTextphải chứa mã JSON dưới dạng văn bản, vì vậy tất cả những gì bạn phải làm là phân tích cú pháp nó bằng 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);

Khả năng tương thích: Cách tiếp cận này sẽ hoạt động với bất kỳ trình duyệt nào hỗ trợ XMLHttpRequestJSON.

JSONHttpRequest

Nếu bạn thích sử dụng responseJSON, nhưng muốn một giải pháp nhẹ hơn JQuery, bạn có thể muốn xem JSONHttpRequest của tôi. Nó hoạt động chính xác như một XMLHttpRequest bình thường, nhưng cũng cung cấp thuộc responseJSONtính. Tất cả những gì bạn phải thay đổi trong mã của mình sẽ là dòng đầu tiên:

var req = new JSONHttpRequest();

JSONHttpRequest cũng cung cấp chức năng để dễ dàng gửi các đối tượng JavaScript dưới dạng JSON. Bạn có thể tìm thấy thêm chi tiết và mã tại đây: http://pixelsvsbytes.com/2011/12/teach-your-xmlhttprequest-some-json/ .

Tiết lộ đầy đủ: Tôi là chủ sở hữu của Pixels | Bytes. Tôi nghĩ rằng kịch bản của tôi là một giải pháp tốt cho vấn đề, vì vậy tôi đã đăng nó ở đây. Hãy để lại bình luận, nếu bạn muốn tôi gỡ bỏ liên kết.


5
+1; IMO đây là câu trả lời thực sự cho câu hỏi - không jQuery chỉ đơn giản là vani cũ XMLHttpRequest; chỉ là câu hỏi về cái gì.
Fergus ở London

s a jquery version too. If you are getting crossbrowser issues thử nó, thường framework`s xử lý những vấn đề này tốt hơn: api.jquery.com/jquery.parsejson
sagits

1
Bốn năm sau và điều này vẫn giúp ích cho mọi người. :) Liên kết với blog là IMO tốt, vì nó thực sự là câu trả lời đầy đủ cho câu hỏi với mã mẫu và tải xuống. Cảm ơn bạn!
user1094821

"Sử dụng thư viện mới" không hữu ích như người ta nghĩ.
Grunion Shaftoe

@GrunionShaftoe Bạn có thể vui lòng giải thích, nghĩa là gì? Tôi không đề nghị sử dụng một thư viện mới. Giải pháp fetchđược đề xuất của tôi là JavaScript chuẩn.
Torben

25

Bạn chỉ cần đặt 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();
  

Tài liệu cho responseType


Có một cảnh báo chính ở đây: cả IE và các phiên bản hiện tại của Edge đều không hỗ trợ điều này (có thể Edge cuối cùng sẽ sau khi chuyển sang Chromium)
Machavity

3

Lưu ý: Tôi chỉ thử nghiệm điều này trong Chrome.

nó thêm một hàm nguyên mẫu vào XMLHttpRequest .. XHR2 ,

trong XHR 1, bạn có thể chỉ cần thay thế this.responsebằngthis.responseText

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

để trả lại json trong xhr2

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

BIÊN TẬP

Nếu bạn định sử dụng XHR với arraybufferhoặc các loại phản hồi khác thì bạn phải kiểm tra xem phản hồi có phải là a không string.

trong mọi trường hợp, bạn phải thêm nhiều kiểm tra hơn, ví dụ như nếu nó không thể phân tích cú pháp json.

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

2
Tôi sẽ xác định một getter thay vì một thuộc tính hàm nếu tôi là bạn. Chỉ cần thay thế valuebằng gettrong đối tượng được chuyển tới Object.defineProperty, và bạn có thể sử dụng responseJSONgiống như bất kỳ biến phản hồi nào khác.
wizzwizz 4

1

Tôi nghĩ rằng bạn phải bao gồm jQuery để sử dụng responseJSON.

Nếu không có jQuery, bạn có thể thử với responseText và thử như eval("("+req.responseText+")");

CẬP NHẬT : Vui lòng đọc bình luận liên quan đến eval, bạn có thể kiểm tra với eval, nhưng không sử dụng nó trong tiện ích mở rộng làm việc.

HOẶC LÀ

sử dụng json_parse : nó không sử dụngeval


5
Đối với một addon Firefox chạy với chrome priv, đừng cố đánh giá bất cứ thứ gì bạn nhận được từ nguồn bên ngoài. Thay vào đó, hãy sử dụng JSON.parse (ít nhất là trong FF 3.5 trở lên).
Ben Combee

1

Sử dụng nsIJSON nếu đây là phần mở rộng 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;
}

Đối với một trang web, chỉ cần sử dụng JSON.parsethay vìComponents.classes["@mozilla.org/dom/json;1"].createInstance(Components.interfaces.nsIJSON.decode

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.