jQuery не аналізує мій JSON із запиту AJAX


88

У мене виникають труднощі з аналізом деяких даних JSON, повернутих із мого сервера за допомогою jQuery.ajax ()

Для виконання AJAX, який я використовую:

$.ajax({
  url: myUrl,
  cache: false,
  dataType: "json",
  success: function(data){
    ...
  },
  error: function(e, xhr){
    ...
  }
});  

І якщо я поверну масив елементів, тоді це буде добре:

[ { title: "One", key: "1" }, { title: "Two", key: "2" } ]

Функція успіху викликається і отримує правильний об'єкт.

Однак, коли я намагаюся повернути один об'єкт:

{ title: "One", key: "1" } 

Викликається функція помилки, і xhr містить 'parsererror'. Я намагався обернути JSON у дужки на сервері, перш ніж відправити його по дроту, але це не має значення. Але якщо я вставляю вміст у рядок у Javascript, а потім використовую функцію eval (), він чудово його оцінює.

Будь-які ідеї, що я роблю не так?

Антоній


Відповіді:


72

Ваш сервер надсилає дані як Content-Type "*/json"? Якщо ні, то відповідно змініть заголовки відповідей. "application/json"Наприклад, надсилання було б непоганим.


По-друге, це припущення, колись у мене була та сама проблема, і я дізнався, що напрочуд я використовував неправильний тип mime. Якщо ви тестуєте через localhost на Windows, дуже добре це знайте. Спробуйте завантажити його кудись і протестувати ще раз. Якщо ви хочете, щоб це працювало на localhost, вам слід дійсно обдурити запит.
Джош

51

Відповідно до специфікації json.org , ваше повернення недійсне. Імена завжди цитуються, тому вам слід повернутися

{ "title": "One", "key": "1" }

і

[ { "title": "One", "key": "1" }, { "title": "Two", "key": "2" } ]

Можливо, це не проблема з вашим налаштуванням, оскільки ви кажете, що одна з них працює зараз, але її слід виправити для правильності на випадок, якщо вам знадобиться перейти на інший парсер JSON у майбутньому.


2
Дійсно, у jQuery 1.4 (наприклад) { key: 'val' }недійсний JSON.
rfunduk

34

Рядки JSON обертаються подвійними лапками; одинарні лапки не є дійсним замінником.

{"who": "Hello World"}

є дійсним, але це не ...

{'who': 'Hello World'}

Хоча це не проблема OP, але вважала, що це варто відзначити для інших, хто тут приземляється.


30

Зазвичай ця проблема пов’язана з тим, що ваш запит отримав неправильний тип mime. При розробці на власному комп’ютері іноді ви не отримуєте належного типу mime від «сервера», яким є ваш власний комп’ютер. Я зіткнувся з цією проблемою один раз при розробці, відкривши локально збережений файл у браузері (наприклад, URL-адреса була "c: /project/test.html").

Спробуйте використовувати властивість beforeSend, щоб додати функцію зворотного виклику, яка замінює тип mime. Це призведе до обману коду, щоб мати справу з json, незважаючи на те, що неправильний тип mime був надісланий сервером і отриманий вашим телефонним кодом. Нижче наведено приклад коду.

Відповідним типом mime є application / json відповідно до цього питання , але я знаю, що application / j-son спрацював, коли я його спробував (зараз кілька років тому). Ймовірно, спочатку слід спробувати application / json.

var jsonMimeType = "application/json;charset=UTF-8";
$.ajax({
 type: "GET",
 url: myURL,
 beforeSend: function(x) {
  if(x && x.overrideMimeType) {
   x.overrideMimeType(jsonMimeType);
  }
 },
 dataType: "json",
 success: function(data){
  // do stuff...
 }
});

просто хочу сказати, що пропозиція beforeSend, яку ви пропонуєте, спрацювала для мене !! мій дзвінок ajax чудово працював у сафарі та хромі, але не у firefox. як тільки я додав beforeSend, тоді Firefox відразу знявся. Ого!! Дякую!!
Karmen Blake

7

У мене була ця проблема, і я трохи використовував її

eval('('+data+')')

отримати дані, що повертаються в об'єкті. але потім пізніше виникли інші проблеми з помилкою `` відсутня) в дужках '' і з'ясувалося, що jQuery має функцію, спеціально для оцінки рядка для структури json:

$.parseJSON(data)

повинен зробити трюк. Це на додаток до того, щоб ваш рядок json був у відповідному форматі, звичайно ..


6

Якщо ви повторюєте відповідь json і ваші заголовки не збігаються з * / json, ви можете використовувати вбудований jQuery.parseJSON api для синтаксичного аналізу відповіді.

response = '{"name":"John"}';
var obj = jQuery.parseJSON(response);
alert( obj.name === "John" );

4
{ title: "One", key: "1" }

Це не те, що ти думаєш. Як вираз, це об’єктний літерал, а як вираз - це:

{                // new block
    title:       // define a label called 'title' for goto statements
        "One",   // statement: the start of an expression which will be ignored
        key:     // ...er, what? you can't have a goto label in the middle of an expression
                 // ERROR

На жаль, eval () не дає вам способу вказати, чи даєте ви йому заяву чи вираз, і він, як правило, вгадує неправильно.

Звичайне рішення - справді обернути що- небудь у дужках перед тим, як надіслати його функції eval (). Ви кажете, що ви пробували це на сервері ... явно якимось чином це не проходить. Це повинно бути водонепроникним, щоб сказати на стороні клієнта, що б не отримував відповідь XMLHttpRequest:

eval('('+responseText+')');

замість:

eval(responseText);

поки відповідь насправді є виразом, а не твердженням. (наприклад, він не має кількох пунктів, розділених крапкою з комою або новою лінією.)


Я думаю, що jQuery автоматично додає дужки під час обробки даних запиту.
Strager

2
Ця відповідь мені дуже допомогла, оскільки я ніколи не розумів, чому люди обертають JSON у дужки.
Андрій Таранцов


2

Якщо ви використовуєте веб-служби ASP.NET за допомогою jQuery, переконайтеся, що у ваш web.config включено:

<webServices>
    <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
    </protocols>
</webServices>

2

У мене була подібна проблема, коли Firefox 3.5 працював нормально та аналізував мої дані JSON, але Firefox 3.0.6 повернув помилку синтаксичного аналізу. Виявилося, що на початку JSON порожній простір спричинив помилку Firefox 3.0.6. Видалення порожнього місця зафіксувало його


2

Методи "eval ()" та "JSON.parse ()" використовують взаємовиключні формати.

  • З "eval ()" потрібні дужки .
  • З "JSON.parse ()" дужки заборонені .

Обережно, є функції "stringify ()", які створюють формат "eval". Для ajax слід використовувати лише формат JSON.

Хоча "eval" включає всю мову JavaScript, JSON використовує лише крихітну підмножину мови. Серед конструкцій на мові JavaScript, які "eval" повинен розпізнавати, є "Блок-оператор" (він же "складний оператор") ; це пара або фігурні дужки "{}" з деякими твердженнями всередині. Але фігурні дужки також використовуються в синтаксисі об’єктних літералів. Інтерпретація диференціюється за контекстом, у якому з’являється код. Щось може виглядати як об’єкт буквальним для вас, але "eval" сприйме це як складене твердження.

У мові JavaScript об’єктні літерали трапляються праворуч від призначення.

var myObj = { ...some..code..here... };

Об’єктивні літерали не виникають самі по собі.

{ ...some..code..here... }   // this looks like a compound statement

Повертаючись до початкового питання, яке було поставлене в 2008 році, він запитав, чому в "eval ()" не вдається виконати наступне:

{ title: "One", key: "1" }

Відповідь полягає в тому, що це виглядає як складене твердження. Щоб перетворити його в об'єкт, потрібно помістити його в контекст, де складене твердження неможливо. Це робиться шляхом наведення дужок навколо нього

( { title: "One", key: "1" } )    // not a compound statment, so must be object literal

OP також запитав , чому подібна заява зробило успішно Eval:

[ { title: "One", key: "1" }, { title: "Two", key: "2" } ]

Застосовується та сама відповідь - фігурні дужки знаходяться в контексті, коли складене твердження неможливо. Це контекст масиву " [...]", і масиви можуть містити об'єкти, але вони не можуть містити оператори.

На відміну від "eval ()", JSON дуже обмежений у своїх можливостях. Обмеження навмисне. Дизайнер JSON задумав мінімалістичну підмножину JavaScript, використовуючи лише синтаксис, який може відображатися праворуч від призначення. Отже, якщо у вас є код, який правильно аналізує в JSON ...

var myVar = JSON.parse("...some...code...here...");

... це означає, що він також буде легально аналізувати з правого боку завдання, як це ..

var myVar = ...some..code..here... ;

Але це не єдине обмеження на JSON. Специфікація мови BNF для JSON дуже проста. Наприклад, він не дозволяє використовувати одинарні лапки для позначення рядків (як це роблять JavaScript та Perl), і він не має способу виразити один символ як байт (як це робить "C"). На жаль, він також не дозволяє коментувати (що було б дуже добре при створенні конфігураційних файлів). Перевагою всіх цих обмежень є те, що синтаксичний аналіз JSON відбувається швидко і не надає можливості для введення коду (загроза безпеці).

Через ці обмеження JSON не використовує дужок. Отже, дужка в рядку JSON є незаконним символом.

Завжди використовуйте формат JSON з ajax з таких причин:

  • Типовий конвеєр ajax буде налаштований для JSON.
  • Використання "eval ()" буде критикуватися як ризик для безпеки.

Як приклад конвеєра ajax, розглянемо програму, яка включає сервер Node та клієнт jQuery. Клієнтська програма використовує виклик jQuery, що має форму $.ajax({dataType:'json',...etc.});. JQuery створює об'єкт jqXHR для подальшого використання, потім пакує та надсилає відповідний запит. Сервер приймає запит, обробляє його, а потім готовий відповісти. Серверна програма викличе метод res.json(data)для упаковки та надішле відповідь. Повернувшись на стороні клієнта, jQuery приймає відповідь, звертається до асоційованого об’єкта jqXHR та обробляє дані у форматі JSON. Все це працює без необхідності ручного перетворення даних. Відповідь не передбачає явного виклику JSON.stringify () на сервері Node і жодного явного виклику JSON.parse () на клієнті; це все для вас.

Використання "eval" пов'язане з ризиками безпеки введення коду. Ви можете подумати, що цього не може статися, але хакери можуть стати досить креативними. Крім того, "eval" є проблематичним для оптимізації Javascript.

Якщо ви виявите, що використовуєте функцію "stringify ()", майте на увазі, що деякі функції з таким ім'ям створюватимуть рядки, сумісні з "eval", а не з JSON. Наприклад, у Node наступне надає вам функцію, яка створює рядки у форматі, сумісному з "eval":

var stringify = require('node-stringify'); // generates eval() format

Це може бути корисно, але якщо у вас немає конкретних потреб, це, мабуть, не те, що ви хочете.


1

Якщо повернення масиву працює, а повернення одного об’єкта - ні, спробуйте також повернути свій єдиний об’єкт як масив, що містить цей об’єкт:

[ { title: "One", key: "1" } ]

таким чином ви повертаєте послідовну структуру даних, масив об’єктів, незалежно від корисного навантаження даних.

я бачу, що ви намагалися обернути свій єдиний об'єкт у "дужки", і пропоную це на прикладі, оскільки, звичайно, JavaScript трактує [..] інакше, ніж (..)


1

Якщо викликається обробник помилок jQuery і об'єкт XHR містить "помилку синтаксичного аналізатора", це, ймовірно, помилка синтаксичного аналізатора, що повертається із сервера.

Чи є ваш сценарій кількох результатів, коли ви викликаєте службу без параметра, але він порушується, коли ви намагаєтесь надати параметр для отримання одного запису?

З якого бекенду ви це повертаєте?

Наприклад, у службах ASMX це часто трапляється, коли параметри передаються в jQuery як об'єкт JSON замість рядка JSON. Якщо ви надаєте jQuery фактичний об'єкт JSON для його параметра "data", він буде серіалізувати це у стандартні & розділені пари k, v замість того, щоб відправляти його як JSON.


1

Я знайшов у деяких своїх реалізаціях, які мені довелося додати:

obj = new Object; obj = (data.obj);

що, здавалося, вирішило проблему. Евал чи ні, здавалося, зробив для мене точно те саме.


Використовуйте літерал об’єкта під час ініціалізації нового об’єкта, а не конструктор об’єкта: var obj = {};
Андреас Грех,

Так, бачу, var myArray = [] для масивів та var myObject = {}, дякую за підказку Dreas
Джей,

1

jQuery задихається на певних клавішах JSON. Я надсилав цей фрагмент JSON у PHP:

echo json_encode((object) array('result' => 'success'));

Перейменування ключа «результат» на щось інше працює. Я вважаю, що це зіткнення зарезервованого слова, яке може бути помилкою в jQuery (1.4.2).


1

У середовищі ColdFusion одна річ, яка може спричинити помилку, навіть із добре сформованим JSON, - це ввімкнення виводу налагодження запитів у адміністраторі ColdFusion (у розділі Налагодження та ведення журналу> Налаштування виведення налагодження). Інформація про налагодження буде повернута з даними JSON і, таким чином, зробить її недійсною.


1

також спробуйте це

$.ajax({
    url: url,
    data:datas,
    success:function(datas, textStatus, jqXHR){
    var returnedData = jQuery.parseJSON(datas.substr(datas.indexOf('{')));
})};

у моєму випадку сервер відповідає невідомим символом перед "{"


1

Я отримував status = parseerror і xhr.status = 200.

Проблема для мене полягала в тому, що URL-адреса всередині відповіді JSON вирішила "\" переключитися на "/".


0

Я боровся з цим і витратив кілька годин, намагаючись це зрозуміти, поки не використав firebug, щоб показати об'єкт даних.

var data = eval("(" + data.responseText + ")");
console.log(data.count);

-1

використання

$data = yourarray(); 
json_encode($data)

на стороні сервера. На стороні клієнта використовуйте ajax з типом даних JSON і переконайтесь, що ваше кодування документа не UTF-8 з BOM, воно повинно бути UTF-8.

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