JQuery.parseJSON выбрасывает ошибку "Недействительный JSON" из-за отсутствия одиночной кавычки в JSON
Выполняя запросы на мой сервер, используя jQuery.post()
, и мой сервер возвращает объекты JSON (например, { "var": "value", ... }
). Однако, если какое-либо из значений содержит одиночную кавычку (правильно экранированное как \'
), jQuery не выполняет синтаксический анализ в противном случае действительной строки JSON. Вот пример того, что я имею в виду (выполненный в консоли Chromes):
data = "{ \"status\": \"success\", \"newHtml\": \"Hello \\\'x\" }";
eval("x = " + data); // { newHtml: "Hello 'x", status: "success" }
$.parseJSON(data); // Invalid JSON: { "status": "success", "newHtml": "Hello \'x" }
Это нормально? Нет ли способа правильно передать одиночную кавычку через JSON?
Ответы
Ответ 1
В соответствии с диаграммой состояния машины на веб-сайте
Обновить - дополнительная информация для интересующих вас:
Дуглас Крокфорд конкретно не говорит, почему спецификация JSON не позволяет избежать одиночных кавычек в строках. Тем не менее, во время обсуждения JSON в Приложение E к JavaScript: Хорошие части, он пишет:
Цели проектирования JSON должны быть минимальными, переносимыми, текстовыми и подмножеством JavaScript. Чем меньше нам нужно согласовать, чтобы взаимодействовать, тем легче мы можем взаимодействовать.
Поэтому, возможно, он решил разрешить строки, которые будут определены с использованием двойных кавычек, поскольку это одно меньшее правило, в котором должны быть согласованы все реализации JSON. В результате невозможно, чтобы один символ кавычки внутри строки случайно завершил строку, потому что по определению строка может быть прервана символом двойной кавычки. Следовательно, нет необходимости разрешать экранирование одного символа кавычки в формальной спецификации.
Копая немного глубже, Crockford org.json реализация JSON для Java более допустима и позволяет использовать одиночные кавычки:
Тексты, создаваемые методами toString, строго соответствуют синтаксическим правилам JSON. Конструкторы более прощающие в текстах, которые они будут принимать:
...
- Строки могут быть указаны с помощью '(одинарная кавычка).
Это подтверждается исходным кодом JSONTokener. Метод nextString
принимает экранированные символы одиночной кавычки и обрабатывает их так же, как символы двойной кавычки:
public String nextString(char quote) throws JSONException {
char c;
StringBuffer sb = new StringBuffer();
for (;;) {
c = next();
switch (c) {
...
case '\\':
c = this.next();
switch (c) {
...
case '"':
case '\'':
case '\\':
case '/':
sb.append(c);
break;
...
В верхней части метода содержится информативный комментарий:
Формальный формат JSON не разрешает строки в одинарных кавычках, но реализация может принимать их.
Таким образом, некоторые реализации будут принимать одинарные кавычки, но вы не должны полагаться на это. Многие популярные реализации в этом отношении весьма ограничительны и будут отклонять JSON, который содержит одиночные кавычки и/или экранированные одинарные кавычки.
Наконец, чтобы связать это с исходным вопросом, jQuery.parseJSON
сначала пытается использовать собственный JSON-анализатор браузера или загруженную библиотеку, такую как json2.js, где это применимо (на стороне примечания есть библиотека, логика jQuery основана на том, если JSON
не определена). Таким образом, jQuery может быть только допустимым, как эта базовая реализация:
parseJSON: function( data ) {
...
// Attempt to parse using the native JSON parser first
if ( window.JSON && window.JSON.parse ) {
return window.JSON.parse( data );
}
...
jQuery.error( "Invalid JSON: " + data );
},
Насколько я знаю, эти реализации только придерживаются официальной спецификации JSON и не принимают одинарные кавычки, поэтому и jQuery.
Ответ 2
Если вам нужна одиночная цитата внутри строки, так как \'undefined по спецификации, используйте \u0027
см. http://www.utf8-chartable.de/ для всех их
edit: пожалуйста, извините мое неправильное использование слова backticks в комментариях. Я имел в виду обратную косую черту. Моя точка зрения заключается в том, что в случае, если у вас есть вложенные строки внутри других строк, я думаю, что может быть более полезным и читаемым использовать unicode вместо большого количества обратных косых черт, чтобы избежать одиночной кавычки. Если вы не вложены, тем не менее, проще просто поставить там простую старую цитату.
Ответ 3
Когда вы отправляете одну цитату в запросе
empid = " T'via"
empid =escape(empid)
Когда вы получите значение, включающее в себя одиночную кавычку
var xxx = request.QueryString("empid")
xxx= unscape(xxx)
Если вы хотите искать/вставлять значение, которое включает одну цитату в запросе
ххх = Replace (EmpID, "'", "'" )
Ответ 4
Я понимаю, где проблема, и когда я смотрю на спецификации, ясно, что необработанные одинарные кавычки должны быть правильно проанализированы.
Я использую функцию jquery`s jQuery.parseJSON для синтаксического анализа строки JSON, но все еще получаю ошибку синтаксического анализа, когда в данных, подготовленных с помощью json_encode, есть одна цитата.
Может быть, ошибка в моей реализации выглядит так (PHP-серверная сторона):
$data = array();
$elem = array();
$elem['name'] = 'Erik';
$elem['position'] = 'PHP Programmer';
$data[] = json_encode($elem);
$elem = array();
$elem['name'] = 'Carl';
$elem['position'] = 'C Programmer';
$data[] = json_encode($elem);
$jsonString = "[" . implode(", ", $data) . "]";
Последний шаг заключается в том, что я храню закодированную строку JSON в переменной JS:
<script type="text/javascript">
employees = jQuery.parseJSON('<?=$marker; ?>');
</script>
Если я использую "вместо" ", он все равно выдает ошибку.
РЕШЕНИЕ:
Единственное, что сработало для меня, было использование битовой маски JSON_HEX_APOS для преобразования одиночных кавычек следующим образом:
json_encode($tmp, JSON_HEX_APOS);
Есть ли другой способ решения этой проблемы? Является ли код неправильным или плохо написанным?
Спасибо
Ответ 5
Удар по аналогичной проблеме с помощью CakePHP для вывода скриптового блока Javascript с использованием PHP json_encode. $contractorCompanies содержит значения, которые имеют одинарные кавычки и как объяснялось выше, и ожидаемые json_encode ($ contractorCompanies) не избегают их, поскольку его действительный JSON.
<?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".(json_encode($contractorCompanies)."' );"); ?>
Добавляя addlashes() вокруг закодированной строки JSON, вы затем избегаете кавычек, позволяя Cake/PHP отсылать правильный JavaScript в браузер. Ошибки JS исчезают.
<?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".addslashes(json_encode($contractorCompanies))."' );"); ?>
Ответ 6
Интересно. Как вы создаете свой JSON на сервере? Вы используете библиотечную функцию (например, json_encode
в PHP), или вы строит строку JSON вручную?
Единственное, что привлекает мое внимание, - это апостроф побега (\'
). Увидев, что вы используете двойные кавычки, как и должно быть, нет необходимости избегать одиночных кавычек. Я не могу проверить, действительно ли это является причиной ошибки jQuery, поскольку я еще не обновлялся до версии 1.4.1.
Ответ 7
Я пытался сохранить объект JSON из XHR-запроса в атрибут data-* HTML5. Я пробовал многие из вышеперечисленных решений без успеха.
Что я, в конечном итоге, делал, заменяя одиночную кавычку '
кодом '
с помощью регулярного выражения после метода stringify(), вызывается следующим образом:
var productToString = JSON.stringify(productObject);
var quoteReplaced = productToString.replace(/'/g, "'");
var anchor = '<a data-product=\'' + quoteReplaced + '\' href=\'#\'>' + productObject.name + '</a>';
// Here you can use the "anchor" variable to update your DOM element.