Вызов jQuery AJAX портит кодировку символов - PullRequest
7 голосов
/ 08 июля 2010

У меня есть сервлет, который выводит JSON. Выходная кодировка для сервлета - ISO-8859-1. Страницы в нашем веб-приложении также настроены на ISO-8859-1. Я бы использовал UTF-8, но это вне моего контроля; мы должны использовать ISO-8859-1.

Когда я сам нажимаю на сервлет, я вижу данные JSON, которые были выведены. Кодировка символов правильная, и ни один из символов не выглядит странно.

Однако, когда я вызываю сервлет через AJAX и использую полученные данные для заполнения поля выбора, я получаю вместо (кажется) всех символов, которые имеют акценты (например, я с серьезным или острым акцентом, dieresis или круговой). Когда я смотрю на ответ на вкладке Net под Firebug, я вижу, что текст выглядит хорошо. Однако, когда я использую эти данные для заполнения поля выбора, я получаю метку с бриллиантом.

Все эти символы являются действительными символами ISO-8859-1, и поэтому я не понимаю, почему они отображаются неправильно.

EDIT

Еще немного информации. Я использую GET в jQuery.ajax, и я установил scriptCharset в ISO-8859-1. На стороне сервера я явно установил кодировку ISO-8859-1, используя request.setCharacterEncoding("ISO-8859-1");

РЕДАКТИРОВАТЬ

Примеры кода:

Это то, что у меня сейчас. Я добавил scriptCharset: "ISO-8859-1" безрезультатно.

        jQuery.ajax({
            url: "/countryAndProvinceCodeServlet",
            data: data,
            dataType: "json",
            type: "GET",
            success: function(data) {
               ...
            },
        });

Мой сервлет использует org.json.JSONObject и просто выводит строку, выполняя response.getWriter().print(jsonObject.toString());

UPDATE

По комментариям о JSON и о том, как это должно быть UTF-8, я пытался посмотреть, смогу ли я получить данные в виде текста (поэтому установите dataType в text в jQuery.ajax) и затем оцените их как JSON сам (в JavaScript). Это тоже не работает! Когда я делаю console.log, я все еще получаю яркие бриллианты. Однако, когда я смотрю на вкладку «Сеть» в Firebug, все выглядит нормально:

Чистая вкладка:

{"error":false,
 "provinces":{"DZ-01":"Adrar",
              "DZ-16":"Alger",
              "DZ-23":"Annaba",
              "DZ-44":"Aïn Defla",
              "DZ-46":"Aïn Témouchent",
              "DZ-05":"Batna",
              "DZ-07":"Biskra",
              "DZ-09":"Blida",
              "DZ-34":"Bordj Bou Arréridj",
              "DZ-10":"Bouira",
              "DZ-35":"Boumerdès",
              "DZ-08":"Béchar",
              "DZ-06":"Béjaïa",
              "DZ-02":"Chlef",
              "DZ-25":"Constantine",
              "DZ-17":"Djelfa",
              "DZ-32":"El Bayadh",
              "DZ-39":"El Oued",
              "DZ-36":"El Tarf",
              "DZ-47":"Ghardaïa",
              "DZ-24":"Guelma",
              "DZ-33":"Illizi",
              "DZ-18":"Jijel",
              "DZ-40":"Khenchela",
              "DZ-03":"Laghouat",
              "DZ-29":"Mascara",
              "DZ-43":"Mila",
              "DZ-27":"Mostaganem",
              "DZ-28":"Msila",
              "DZ-26":"Médéa",
              "DZ-45":"Naama",
              "DZ-31":"Oran",
              "DZ-30":"Ouargla",
              "DZ-04":"Oum el Bouaghi",
              "DZ-48":"Relizane",
              "DZ-20":"Saïda",
              "DZ-22":"Sidi Bel Abbès",
              "DZ-21":"Skikda",
              "DZ-41":"Souk Ahras",
              "DZ-19":"Sétif",
              "DZ-11":"Tamanghasset",
              "DZ-14":"Tiaret",
              "DZ-37":"Tindouf",
              "DZ-42":"Tipaza",
              "DZ-38":"Tissemsilt",
              "DZ-15":"Tizi Ouzou",
              "DZ-13":"Tlemcen",
              "DZ-12":"Tébessa"}}

Но когда я делаю console.log(text) с тем, что получаю от jQuery.ajax, я получаю следующее:

{"error":false,
 "provinces":{"DZ-01":"Adrar",
              "DZ-16":"Alger",
              "DZ-23":"Annaba",
              "DZ-44":"A�n Defla",
              "DZ-46":"A�n T�mouchent",
              "DZ-05":"Batna",
              "DZ-07":"Biskra",
              "DZ-09":"Blida",
              "DZ-34":"Bordj Bou Arr�ridj",
              "DZ-10":"Bouira",
              "DZ-35":"Boumerd�s",
              "DZ-08":"B�char",
              "DZ-06":"B�ja�a",
              "DZ-02":"Chlef",
              "DZ-25":"Constantine",
              "DZ-17":"Djelfa",
              "DZ-32":"El Bayadh",
              "DZ-39":"El Oued",
              "DZ-36":"El Tarf",
              "DZ-47":"Gharda�a",
              "DZ-24":"Guelma",
              "DZ-33":"Illizi",
              "DZ-18":"Jijel",
              "DZ-40":"Khenchela",
              "DZ-03":"Laghouat",
              "DZ-29":"Mascara",
              "DZ-43":"Mila",
              "DZ-27":"Mostaganem",
              "DZ-28":"Msila",
              "DZ-26":"M�d�a",
              "DZ-45":"Naama",
              "DZ-31":"Oran",
              "DZ-30":"Ouargla",
              "DZ-04":"Oum el Bouaghi",
              "DZ-48":"Relizane",
              "DZ-20":"Sa�da",
              "DZ-22":"Sidi Bel Abb�s",
              "DZ-21":"Skikda",
              "DZ-41":"Souk Ahras",
              "DZ-19":"S�tif",
              "DZ-11":"Tamanghasset",
              "DZ-14":"Tiaret",
              "DZ-37":"Tindouf",
              "DZ-42":"Tipaza",
              "DZ-38":"Tissemsilt",
              "DZ-15":"Tizi Ouzou",
              "DZ-13":"Tlemcen",
              "DZ-12":"T�bessa"}}

Мне кажется, что jQuery делает что-то странное с данными.

Ответы [ 6 ]

17 голосов
/ 08 июля 2010

Я наконец понял это.Это довольно странно!

response.setCharacterEncoding(String) делает не работу (не знаю, связано ли это с моей настройкой или с чем).Похоже, он устанавливает кодировку символов, но по какой-то причине jQuery все испортил.Вы явно задаете заголовки следующим образом:

response.setHeader("Content-Type", "application/json; charset=ISO-8859-1");

Спасибо всем за помощь, всем!

РЕДАКТИРОВАТЬ

Я провел небольшое исследованиеи проверил JavaDocs и увидел это:

Контейнеры должны передавать кодировку символов, используемую для средства записи ответа сервлета, клиенту, если протокол предоставляет способ сделать это.В случае HTTP кодировка символов передается как часть заголовка Content-Type для текстовых типов мультимедиа. Обратите внимание, что кодировка символов не может передаваться через заголовки HTTP , если сервлет не указывает тип содержимого ;тем не менее, он все еще используется для кодирования текста, написанного с помощью средства записи ответа сервлета .

Таким образом, вышеприведенное все еще работает, но вы также можете (и, вероятно, должны) это сделать:1030 *

1 голос
/ 08 июля 2010

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

Вы можете попытаться вставить в jQuery.ajax дополнительный параметр

dataFilter : function ( data, type ) {
    alert(data);
    return data;
}

Если у вас будут неправильные, но разные символы для всех не-ASCII символов ('ï', 'é' и т. Д.), Вы можете попробовать заменить неправильные закодированные символы на правильные символы и вернутьправильные закодированные данные из dataFilter.

1 голос
/ 08 июля 2010

RFC 4627 утверждает, что текст JSON ДОЛЖЕН быть закодирован в Unicode, что бы это ни значило, а json.org указывает, что все символы являются «символами Unicode»:

  • Кодировка

    Текст JSON ДОЛЖЕН быть закодирован в Unicode.Кодировка по умолчанию - UTF-8.

    Поскольку первые два символа текста JSON всегда будут символами ASCII [RFC0020], можно определить, является ли поток октетов UTF-8, UTF-16 (BE или LE) или UTF-32 (BE или LE), взглянув на шаблон нулей в первых четырех октетах.

       00 00 00 xx  UTF-32BE
       00 xx 00 xx  UTF-16BE
       xx 00 00 00  UTF-32LE
       xx 00 xx 00  UTF-16LE
       xx xx xx xx  UTF-8
    

Так что если вы переносите JSON иговоря, что это ISO-8859-1, различные библиотеки JSON могут интерпретировать предложение SHALL из RFC, которое определяет JSON различными способами, например, путем кодирования символа замены или путем анализа кода.Наилучший способ, если, очевидно, принять это к тому, что находится вне вашего контроля, и попросить их исправить это: -)

Обходные пути

Один из способов обойти это - создать фильтр сервлетов, который удаляетвсе символы, которые несовместимы как с UTF-8, так и с ISO-8859-1, и замените их на экранирование JSON:

В следующем фрагменте замените 'é' на '\ u00E9', чтобы любой нарушающий ISO-8859-1 символ безопасно переносится в 7-битных идентичных символах:

До: { "a" : "éte" }

После: { "a" : "\u00E9te" }

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

1 голос
/ 08 июля 2010

Можете ли вы вместо этого использовать UTF-8?

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

В PHP вы можете кодировать данные JSON как UTF-8:

/**
 * Applies a UTF-8 encoding conversion for text.
 */
function utf8_enc( $rows ) {
  $encoded = array();

  foreach( $rows as $row ) {
    $temp = array();

    foreach( $row as $name => $value ) {
      $temp[ $name ] = $value = mb_convert_encoding( $value, 'auto', 'UTF-8' );
    }

    array_push( $encoded, $temp );
  }

  return $encoded;
}

function db_json( $query ) {
  echo json_encode( utf8_enc( db_fetch_all( db_query( $query ) ) ) );
}

Я видел странные результаты, используянабор символов с акцентом на ISO-8859-1.Я переключился на UTF-8, и проблемы с кодированием исчезли.

Для чего я это сделал, я кодировал getJSON следующим образом:

  $.getJSON( HOST + 'cat.dhtml', function( data ) {
    var h = '';
    var len = data.length;

    for( var i = 0; i < len; i++ ) {
      h += '<option value="' + data[i].id + '">' + data[i].name + '</option>';
      categories[ data[i].id ] = data[i];
    }

    $('#category').html(h);
  });
0 голосов
/ 22 декабря 2015

Если вы хотите получить данные из базы данных, вы должны написать их под предложениями на странице, которая отправляет запрос со страницы ajax.Например, если вы пишете код HTML и AJAX на странице «A» и отправляете переменную из кода Java на страницу «B», напишите эти коды на странице «B».
не забывайте, что ваша база данных должна быть в режиме Unicode, напримеркак "utf8_general_ci".

mysqli_query ($conn,"set character_set_client='utf8'");
mysqli_query ($conn,"set character_set_results='utf8'");
mysqli_query ($conn,"set collation_connection='utf8_general_ci'");
mysqli_query($conn,"set collation_connection='utf8_persian_ci'");
mysqli_set_charset($conn,"set character_set_results='utf8'") ;
mysqli_set_charset($conn,"set collation_connection='utf8_general_ci'") ;

;Я написал это предложение для персидского языка, вы можете изменить его.$conn - переменная для подключения к указанной таблице в базе данных MySQL.

0 голосов
/ 08 июля 2010

Функция php json_encode не поддерживает данные в кодировке ISO-8859-1.

Эта статья может помочь вам решить вашу проблему: http://www.pabloviquez.com/2009/07/json-iso-8859-1-and-utf-8-%E2%80%93-part2/

...