Розбір JSON із XmlHttpRequest.responseJSON


99

Я намагаюся трохи проаналізувати відповідь JSON у javascript.

Я отримую 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? Або що не так із цим кодом?

Відповіді:


227

Нові способи я: fetch

TL; DR Я б рекомендував цей спосіб, якщо вам не доведеться надсилати синхронні запити або підтримувати старі браузери.

Поки ваш запит асинхронний, ви можете використовувати API Fetch для надсилання запитів HTTP. API вибору працює з обіцянками , що є чудовим способом обробки асинхронних робочих процесів у JavaScript. За допомогою цього підходу ви використовуєте fetch()для надсилання запиту та ResponseBody.json()аналізу відповіді:

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

Сумісність: API Fetch не підтримується IE11, а також Edge 12 і 13. Однак існують полізаливки .

Нові шляхи II: responseType

Як писав у своїй відповіді Лондерен , новіші браузери дозволяють використовувати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. Поки bitly дійсно відповідає на ваш запит деяким 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);

Сумісність: Цей підхід повинен працювати з будь-яким браузером, який підтримує XMLHttpRequestтаJSON .

JSONHttpRequest

Якщо ви віддаєте перевагу використанню responseJSON, але хочете більш легке рішення, ніж JQuery, ви можете перевірити мій JSONHttpRequest. Він працює точно так само, як звичайний XMLHttpRequest, але також надає responseJSONвластивість. Все, що вам потрібно змінити у коді, буде перший рядок:

var req = new JSONHttpRequest();

JSONHttpRequest також надає функціональність для легкої надсилання об'єктів JavaScript як JSON. Детальніше та код можна знайти тут: http://pixelsvsbytes.com/2011/12/teach-your-xmlhttprequest-some-json/ .

Повна інформація: Я є власником пікселів | байтів. Я думаю, що мій сценарій є гарним рішенням проблеми, тому я розмістив його тут. Будь ласка, залиште коментар, якщо ви хочете, щоб я видалив посилання.


5
+1; IMO це була справжня відповідь на запитання - жоден jQuery не просто звичайна стара ваніль XMLHttpRequest; саме про те, про яке питання йшлося.
Фергюс у Лондоні

Там s a jquery version too. If you are getting crossbrowser issueспробуйте, зазвичай фреймворк краще справляється з цими проблемами: api.jquery.com/jquery.parsejson
sagits

1
Через чотири роки це все ще допомагає людям. :) Посилання на блог є чудовим IMO, оскільки це справді повна відповідь на питання із зразком коду та завантаженням. Дякую!
user1094821

"Використовувати нову бібліотеку" не настільки корисно, як можна подумати.
Grunion Shaftoe

@GrunionShaftoe Не могли б ви пояснити, що це означає? Я не пропоную використовувати нову бібліотеку. Моє рекомендоване рішення fetch- це стандартний JavaScript.
Торбен

25

Ви можете просто встановити 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();
  

Документація для відповідіType


Тут є головне застереження: ні 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());
}

EDIT

Якщо ви плануєте використовувати 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
На вашому місці я б визначив геттер замість атрибута функції. Просто замініть valueна getв переданому об'єкті Object.defineProperty, і ви можете використовувати, responseJSONяк будь-яку іншу змінну відповіді.
wizzwizz4

1

Я думаю, вам потрібно включити jQuery для використання responseJSON.

Без jQuery ви можете спробувати з responseText і спробувати лайк eval("("+req.responseText+")");

ОНОВЛЕННЯ : Будь ласка, прочитайте коментар щодо eval, ви можете тестувати за допомогою eval, але не використовуйте його в робочому розширенні.

АБО

використовуйте json_parse : він не використовуєeval


5
Для аддону Firefox, який працює з chrome privs, не намагайтеся оцінювати все, що ви отримуєте із зовнішнього джерела. Натомість використовуйте JSON.parse (принаймні у FF 3.5 та пізніших версіях).
Бен Комбі

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.