jQuery не будет анализировать мой JSON из запроса AJAX - PullRequest
87 голосов
/ 30 октября 2008

У меня проблемы с анализом некоторых данных 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 (), он оценит его отлично.

Есть идеи, что я делаю не так?

Anthony

Ответы [ 20 ]

71 голосов
/ 30 октября 2008

Ваш сервер отправляет данные как Content-Type "*/json"? Если нет, измените заголовки ответа соответственно. Отправка "application/json" будет в порядке, например.

51 голосов
/ 30 октября 2008

Согласно спецификации json.org , ваше возвращение недействительно. Имена всегда в кавычках, поэтому вы должны возвращать

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

и

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

Это может не быть проблемой с вашей настройкой, поскольку вы говорите, что одна из них работает сейчас, но она должна быть исправлена ​​для корректности на случай, если в будущем вам потребуется переключиться на другой анализатор JSON.

33 голосов
/ 26 марта 2010

JSON-строки заключены в двойные кавычки; одинарные кавычки не являются допустимой заменой.

{"who": "Hello World"}

допустимо, но это не ...

{'who': 'Hello World'}

Хотя это и не проблема ОП, но стоит подумать о тех, кто здесь приземлится.

30 голосов
/ 30 октября 2008

Эта проблема обычно связана с тем, что ваш запрос получил неправильный тип пантомимы. При разработке на своем компьютере иногда вы не получаете правильный тип пантомимы с «сервера», который является вашим собственным компьютером. Я столкнулся с этой проблемой один раз при разработке, открыв локально сохраненный файл в браузере (например, 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...
 }
});
7 голосов
/ 17 декабря 2010

У меня была эта проблема, и немного я использовал

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

для получения данных, возвращаемых в объекте. но потом возникли другие проблемы, связанные с ошибкой «отсутствует в скобках», и выяснилось, что в jQuery есть функция, специально предназначенная для вычисления строки для структуры json:

$.parseJSON(data)

должен сделать свое дело. Это в дополнение к наличию вашей строки JSON в правильном формате, конечно ..

6 голосов
/ 17 мая 2012

Если вы выводите ответ json и ваши заголовки не совпадают * / json, то вы можете использовать встроенный jQuery.parseJSON api для анализа ответа.

response = '{"name":"John"}';
var obj = jQuery.parseJSON(response);
alert( obj.name === "John" );
4 голосов
/ 30 октября 2008
{ title: "One", key: "1" }

Это не то, что вы думаете. Как выражение, это литерал Object, но как выражение:

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

до тех пор, пока ответ действительно является выражением, а не утверждением. (например, он не имеет нескольких разделенных точкой с запятой или символом новой строки.)

3 голосов
/ 27 июля 2014

Вам нужно будет установить тип содержимого заголовка в вашем php следующим образом:

 <?php

 header('Content-type:application/json');

 ?>

Посмотрите эти видео для лучшего понимания ....

Ссылка: http://www.youtube.com/watch?v=EvFXWqEqh6o

2 голосов
/ 13 ноября 2016

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

  • С круглыми скобками "eval ()" требуется .
  • С круглыми скобками "JSON.parse ()" запрещено .

Осторожно, есть функции "stringify ()", которые создают формат "eval". Для ajax вы должны использовать только формат JSON.

В то время как «eval» включает в себя весь язык JavaScript, JSON использует лишь небольшую часть языка. Среди конструкций на языке JavaScript, которые должен распознавать eval, есть «Оператор блока» (a.k.a. «Составной оператор») ; которая представляет собой пару или фигурные скобки "{}" с некоторыми инструкциями внутри. Но фигурные скобки также используются в синтаксисе объектных литералов. Интерпретация дифференцируется контекстом, в котором появляется код. Что-то может выглядеть как объект, буквальный для вас, но «eval» увидит это как составное утверждение.

На языке JavaScript литералы объектов встречаются справа от присваивания.

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

Литералы объектов не встречаются сами по себе.

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

Возвращаясь к первоначальному вопросу OP, заданному в 2008 году, он спросил, почему в eval () не удается выполнить следующее:

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

Ответ в том, что это выглядит как сложное утверждение. Чтобы преобразовать его в объект, вы должны поместить его в контекст, где составное утверждение невозможно. Это можно сделать, поставив вокруг него скобки

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

ОП также спросил, почему подобное утверждение успешно успешно подтвердилось:

[ { 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

Это может быть полезно, но если у вас нет особых потребностей, это, вероятно, не то, что вы хотите.

2 голосов
/ 27 января 2010

У меня была похожая проблема, когда Firefox 3.5 работал нормально и анализировал мои данные JSON, но Firefox 3.0.6 вернул ошибку синтаксического анализа. Оказалось, что это было пустое место в начале JSON, из-за которого Firefox 3.0.6 выдавал ошибку. Удаление пробела исправлено

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...