การแยกวิเคราะห์ JSON จาก XmlHttpRequest.responseJSON


104

ฉันพยายามแยกวิเคราะห์การตอบสนอง JSON เล็กน้อยในจาวาสคริปต์

ฉันได้รับ JSON ผ่าน 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;  
}

ฉันทำสิ่งนี้ในส่วนเสริม firefox เมื่อฉันเรียกฉันได้รับข้อผิดพลาด "jsonResponse จะไม่ได้กำหนด" var bitlyUrl = jsonResponse.results[url].shortUrl;สำหรับบรรทัด ฉันทำอะไรผิดในการแยกวิเคราะห์ JSON ที่นี่หรือไม่ หรือโค้ดนี้ผิดพลาดอะไร

คำตอบ:


236

วิธีใหม่ที่ฉัน: fetch

TL; DRขอแนะนำวิธีนี้ตราบใดที่คุณไม่ต้องส่งคำขอซิงโครนัสหรือรองรับเบราว์เซอร์เก่า

ตราบใดที่คำขอของคุณเป็นแบบอะซิงโครนัสคุณสามารถใช้Fetch APIเพื่อส่งคำขอ HTTP API การดึงข้อมูลทำงานร่วมกับสัญญาซึ่งเป็นวิธีที่ดีในการจัดการเวิร์กโฟลว์แบบอะซิงโครนัสใน JavaScript ด้วยวิธีนี้คุณใช้fetch()เพื่อส่งคำขอและResponseBody.json()แยกวิเคราะห์การตอบกลับ:

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

เข้ากันได้: ดึงข้อมูล API ไม่ได้รับการสนับสนุนโดย IE11 เช่นเดียวกับขอบ 12 และ 13 แต่มีpolyfills

วิธีใหม่ II: responseType

ดังที่Londerenได้เขียนไว้ในคำตอบของเขาเบราว์เซอร์รุ่นใหม่อนุญาตให้คุณใช้responseTypeคุณสมบัติเพื่อกำหนดรูปแบบที่คาดหวังของการตอบกลับ จากนั้นข้อมูลการตอบกลับที่แยกวิเคราะห์สามารถเข้าถึงได้ผ่าน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);

ความเข้ากันได้: responseType = 'json'IE11 ไม่รองรับ

วิธีคลาสสิก

XMLHttpRequest มาตรฐานไม่มีresponseJSONคุณสมบัติเพียงresponseTextและresponseXML. ตราบใดที่บางส่วนตอบสนองด้วย JSON สำหรับคำขอของคุณอย่างแท้จริงresponseTextควรมีโค้ด JSON เป็นข้อความดังนั้นสิ่งที่คุณต้องทำคือแยกวิเคราะห์ด้วย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);

เข้ากันได้: วิธีการนี้ควรทำงานร่วมกับเบราว์เซอร์ใด ๆ ที่สนับสนุนและXMLHttpRequestJSON

JSONHttpRequest

หากคุณต้องการใช้responseJSONแต่ต้องการโซลูชันที่มีน้ำหนักเบากว่า JQuery คุณอาจต้องการตรวจสอบ JSONHttpRequest ของฉัน มันทำงานเหมือนกับ XMLHttpRequest ทั่วไป แต่ยังให้responseJSONคุณสมบัติ สิ่งที่คุณต้องเปลี่ยนในรหัสของคุณคือบรรทัดแรก:

var req = new JSONHttpRequest();

JSONHttpRequest ยังมีฟังก์ชันในการส่งวัตถุ JavaScript เป็น JSON ได้อย่างง่ายดาย รายละเอียดเพิ่มเติมและรหัสที่สามารถพบได้ที่นี่: http://pixelsvsbytes.com/2011/12/teach-your-xmlhttprequest-some-json/

การเปิดเผยข้อมูลทั้งหมด: ฉันเป็นเจ้าของ Pixels | Bytes ฉันคิดว่าสคริปต์ของฉันเป็นทางออกที่ดีสำหรับคำถามเดิม แต่มันค่อนข้างล้าสมัยในปัจจุบัน ไม่แนะนำให้ใช้อีกต่อไป


6
+1; IMO นี้คือคำตอบที่แท้จริงสำหรับคำถาม - ไม่มี jQuery เพียงวานิลลาเก่าธรรมดาXMLHttpRequest; คำถามเกี่ยวกับอะไร
เฟอร์กัสในลอนดอน

มีs a jquery version too. If you are getting crossbrowser issues ลองมันมักจะ framework`s จัดการปัญหาเหล่านี้ดีกว่า: api.jquery.com/jquery.parsejson
sagits

1
สี่ปีต่อมาและสิ่งนี้ยังคงช่วยเหลือผู้คน :) การเชื่อมโยงไปยังบล็อกเป็น IMO ที่ดีเนื่องจากเป็นคำตอบที่สมบูรณ์สำหรับคำถามพร้อมรหัสตัวอย่างและการดาวน์โหลด ขอขอบคุณ!
user1094821

"ใช้ห้องสมุดใหม่" ไม่เป็นประโยชน์อย่างที่คิด
Sean Munson

@GrunionShaftoe คุณช่วยอธิบายได้ไหมว่าหมายความว่าอย่างไร? ฉันไม่ได้แนะนำให้ใช้ห้องสมุดใหม่ โซลูชันที่ฉันแนะนำfetchคือ JavaScript มาตรฐาน
Torben

26

คุณสามารถตั้งค่า 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();
  

เอกสารประกอบสำหรับ responseType


มีข้อแม้สำคัญอยู่ที่นี่: ทั้ง IE หรือ Edge เวอร์ชันปัจจุบันไม่รองรับสิ่งนี้ (ในที่สุด Edge อาจจะเปลี่ยนเป็น Chromium)
Machavity

3

หมายเหตุ: ฉันได้ทดสอบสิ่งนี้ใน Chrome เท่านั้น

มันเพิ่มฟังก์ชันต้นแบบให้กับ XMLHttpRequest .. XHR2 ,

ในXHR 1 คุณอาจต้องแทนที่this.responseด้วยthis.responseText

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

เพื่อส่งคืน json ใน xhr2

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

แก้ไข

หากคุณวางแผนที่จะใช้ XHR กับarraybufferหรือประเภทการตอบกลับอื่น ๆ คุณต้องตรวจสอบว่าการตอบกลับเป็นไฟล์string.

ไม่ว่าในกรณีใดคุณต้องเพิ่มการตรวจสอบเพิ่มเติมเช่นหากไม่สามารถแยกวิเคราะห์ json ได้

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

2
ฉันจะกำหนดgetterแทนคุณสมบัติของฟังก์ชันถ้าฉันเป็นคุณ เพียงแค่แทนที่valueด้วยgetในออบเจ็กต์ที่ส่งไปยังObject.definePropertyและคุณสามารถใช้responseJSONเหมือนกับที่คุณทำกับตัวแปรการตอบสนองอื่น ๆ
wizzwizz4

1

ฉันคิดว่าคุณต้องรวม jQuery responseJSONกับการใช้งาน

หากไม่มี jQuery คุณสามารถลองใช้ responseText และลองชอบ eval("("+req.responseText+")");

UPDATE : โปรดอ่านความคิดเห็นเกี่ยวกับevalคุณสามารถทดสอบด้วย eval แต่อย่าใช้ในส่วนขยายการทำงาน

หรือ

ใช้json_parse : ไม่ใช้ไฟล์eval


5
สำหรับส่วนเสริม Firefox ที่ทำงานด้วย chrome privs อย่าพยายามประเมินสิ่งที่คุณได้รับจากแหล่งภายนอก ให้ใช้ JSON.parse แทน (อย่างน้อยใน FF 3.5 ขึ้นไป)
Ben Combee

1

ใช้nsIJSONหากเป็นส่วนขยาย 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;
}

สำหรับหน้าเว็บให้ใช้JSON.parseแทนComponents.classes["@mozilla.org/dom/json;1"].createInstance(Components.interfaces.nsIJSON.decode

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.