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. Я пробовал многие из вышеперечисленных решений без успеха.

Что я, в конечном итоге, делал, заменяя одиночную кавычку ' кодом &#39; с помощью регулярного выражения после метода stringify(), вызывается следующим образом:

var productToString = JSON.stringify(productObject);
var quoteReplaced = productToString.replace(/'/g, "&#39;");
var anchor = '<a data-product=\'' + quoteReplaced + '\' href=\'#\'>' + productObject.name + '</a>';
// Here you can use the "anchor" variable to update your DOM element.