jQuery не будет анализировать мой JSON из запроса AJAX

82

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

Любые идеи, что я делаю неправильно?

Энтони

Теги:

20 ответов

70
Лучший ответ

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

  • 0
    Во-вторых, у меня была такая же проблема, и я узнал, что на удивление я использовал неправильный тип пантомимы. Если вы тестируете на локальном хосте в Windows, знайте об этом. Попробуйте загрузить его где-нибудь и протестировать снова. Если вы хотите, чтобы он работал на локальном хосте, вы должны действительно выдумать запрос.
49

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

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

и

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

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

  • 2
    Действительно, в jQuery 1.4 (например) { key: 'val' } не является допустимым JSON.
32

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

{"who": "Hello World"}

но это не...

{'who': 'Hello World'}

Несмотря на то, что проблема с ОП, считалось, стоит отметить других, которые приземляются здесь.

29

Эта проблема обычно возникает из-за того, что ваш запрос получил неправильный тип mime. При разработке на вашем собственном компьютере иногда вы не получаете правильный тип mime с "сервера", который является вашим собственным компьютером. Однажды я столкнулся с этой проблемой при разработке, открыв локально сохраненный файл в браузере (например, URL был "c:/project/test.html" ).

Попробуйте использовать свойство beforeSend для добавления функции обратного вызова, которая переопределяет тип mime. Это обманет код в работе с json, несмотря на неправильный тип mime, отправляемый сервером и полученный вашим кодом вызова. Ниже приведен пример кода ниже.

Правильный тип mime - application/json в соответствии с этим вопросом, но я знаю, что приложение /j -son работало, когда я его пробовал (теперь несколько лет назад). Вероятно, вы должны сначала попробовать приложение /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...
 }
});
  • 0
    просто хочу сказать, что предложенное вами предложение "Перед отправкой" сработало для меня !! Мой вызов ajax отлично работал в сафари и хроме, но не в Firefox. как только я добавил beforeSend, Firefox сразу же начал работу. Вот это да!! Спасибо!!
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" }

Не то, что вы думаете. В качестве выражения это литерал 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);

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

  • 0
    Я думаю, что jQuery добавляет скобки автоматически при обработке данных запроса.
  • 2
    Этот ответ был очень полезен для меня, так как я никогда не понимал, почему люди заключают JSON в скобки.
2

Методы "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

OP также спросил, почему успешная оценка аналогичного оператора :

[ { 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 do), и у него нет способа выразить один символ в виде байта (например, "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

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

 <?php

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

 ?>

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

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

2

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

2

Если вы используете веб-службы ASP.NET с помощью jQuery, убедитесь, что в вашем web.config указано следующее:

<webServices>
    <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
    </protocols>
</webServices>
  • 1
    Крайне важно для работы веб-сервисов jQuery и .NET.
1

Я получал статус = parseerror и xhr.status = 200.

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

1

попробуйте это

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

в моем случае сервер отвечает неявным символом до '{'

1

В среде ColdFusion одна вещь, которая приведет к ошибке, даже с хорошо сформированным JSON, включает Включить вывод отладки запроса в ColdFusion Administrator (в разделе "Отладка и ведение журнала" > "Отладочный вывод" Настройки). Отладочная информация будет возвращена с данными JSON и, таким образом, сделает ее недействительной.

1

jQuery зажимает определенные ключи JSON. Я отправил этот фрагмент JSON в PHP:

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

Переименование ключа "результат" на что-то еще работает. Я бы предположил, что это зарезервированное словосочетание какого-то типа, и может быть ошибкой в ​​jQuery (1.4.2).

1

В некоторых моих реализациях я добавил:

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

который, казалось, решил проблему. Eval, или нет, это казалось для меня одинаковым.

  • 0
    При инициализации нового объекта используйте литерал объекта, а не конструктор объекта: var obj = {};
  • 0
    Да, я вижу, var myArray = [] для массивов и var myObject = {}, спасибо за подсказку Dreas
1

Если вызывается обработчик ошибок jQuery и объект XHR содержит "ошибку парсера", возможно, ошибка с парсером возвращается с сервера.

Является ли ваш сценарий множественного результата при вызове службы без параметра, но он ломается, когда вы пытаетесь предоставить параметр для получения одной записи?

Какой бэкэнд вы возвращаете?

В службах ASMX, например, часто бывает, когда параметры передаются в jQuery как объект JSON вместо строки JSON. Если вы предоставите jQuery реальный объект JSON для своего параметра "data", он будет сериализовать это в стандартные и ограниченные пары k, v вместо отправки его как JSON.

1

Если возврат массива работает и возврат одного объекта не выполняется, вы также можете попробовать вернуть свой единственный объект в виде массива, содержащего этот единственный объект:

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

таким образом вы возвращаете согласованную структуру данных, массив объектов, независимо от полезной нагрузки данных.

Я вижу, что вы попытались обернуть свой единственный объект в "скобках" и предложите это с помощью примера, потому что JavaScript, кстати, обрабатывает [..] иначе, чем (..)

0

использование

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

на стороне сервера. На стороне клиента используйте ajax с Datatype JSON и убедитесь, что ваша кодировка документов не UTF-8 с спецификацией, она должна быть UTF-8.

0

Я боролся с этим и провел несколько часов, пытаясь понять это, пока я не использовал firebug для отображения объекта данных.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню