У меня есть сценарий Perl CGI, который обращается к тайскому языку, строкам UTF-8 из базы данных PostgreSQL и возвращает их веб-интерфейсу в виде JSON.Строки в порядке, когда я получаю их из БД и после того, как кодирую их как JSON (на основе записи в файл журнала).Тем не менее, когда клиент получает их, они повреждены, например:
имя_компонента "¸ \ u0094ภาภ© ี "
Очевидно, что некоторые символы конвертируются в escape-последовательности Unicode, но не все.
Я действительно мог бы использовать некоторые предложения, как решить эту проблему.
Ниже приведен упрощенный фрагмент кода.Я использую utf8 и utf8 :: all, а также JSON.
Заранее благодарен за любую помощь, которую вы можете предоставить.
my $dataId = $cgi->param('dataid');
my $table = "uploadpoints";
my $sqlcommand = "select id,featurename from $table where dataid=$dataId;";
my $stmt = $gDbh->prepare($sqlcommand);
my $numrows = $stmt->execute;
# print JSON header
print <<EOM;
Content-type: application/json; charset="UTF-8"
EOM
my @retarray;
for (my $i = 0; ($i < $numrows); $i=$i+1)
{
my $hashref = $stmt->fetchrow_hashref("NAME_lc");
#my $featurename = $hashref->{'featurename'};
#logentry("Point $i feature name is: $featurename\n");
push @retarray,$hashref;
}
my $json = encode_json (\@retarray);
logentry("JSON\n $json");
print $json;
Я изменил иУпрощенный пример, теперь выполняется локально, а не через вызов браузера:
my $dataId = 5;
my $table = "uploadpoints";
my $sqlcommand = "select id,featurename from $table where dataid=$dataId and id=75;";
my $stmt = $gDbh->prepare($sqlcommand);
my $numrows = $stmt->execute;
my @retarray;
for (my $i = 0; ($i < $numrows); $i=$i+1)
{
my $hashref = $stmt->fetchrow_hashref("NAME_lc");
my $featurename = $hashref->{'featurename'};
print "featurename $featurename\n";
push @retarray,$hashref;
}
my $json = encode_json (\@retarray);
print $json;
Используя hexdump, как в примере Стефана, я определил, что данные, считанные из базы данных, уже находятся в UTF-8.Похоже, что они перекодируются в методе кодирования JSON.Но почему?
Данные в JSON используют ровно в два раза больше байтов, чем исходный UTF-8.
perl testcase.pl | hexdump -C
00000000 66 65 61 74 75 72 65 6e 61 6d 65 20 e0 b9 82 e0 |featurename ....|
00000010 b8 a3 e0 b8 87 e0 b9 80 e0 b8 a3 e0 b8 b5 e0 b8 |................|
00000020 a2 e0 b8 99 e0 b9 81 e0 b8 88 e0 b9 88 e0 b8 a1 |................|
00000030 e0 b8 88 e0 b8 b1 e0 b8 99 e0 b8 97 e0 b8 a3 e0 |................|
00000040 b9 8c 0a 5b 7b 22 66 65 61 74 75 72 65 6e 61 6d |...[{"featurenam|
00000050 65 22 3a 22 c3 a0 c2 b9 c2 82 c3 a0 c2 b8 c2 a3 |e":"............|
00000060 c3 a0 c2 b8 c2 87 c3 a0 c2 b9 c2 80 c3 a0 c2 b8 |................|
00000070 c2 a3 c3 a0 c2 b8 c2 b5 c3 a0 c2 b8 c2 a2 c3 a0 |................|
00000080 c2 b8 c2 99 c3 a0 c2 b9 c2 81 c3 a0 c2 b8 c2 88 |................|
00000090 c3 a0 c2 b9 c2 88 c3 a0 c2 b8 c2 a1 c3 a0 c2 b8 |................|
000000a0 c2 88 c3 a0 c2 b8 c2 b1 c3 a0 c2 b8 c2 99 c3 a0 |................|
000000b0 c2 b8 c2 97 c3 a0 c2 b8 c2 a3 c3 a0 c2 b9 c2 8c |................|
000000c0 22 2c 22 69 64 22 3a 37 35 7d 5d |","id":75}]|
000000cb
Есть еще предложения?Я попытался использовать декодирование в строке UTF, но получил ошибки, связанные с широкими символами.
Я прочитал рекомендованный ответ Тома Кристиансона, а также его учебники по Юникоду, но я признаю, что многое из этого пошло мне на ум.Кроме того, кажется, что моя проблема значительно более ограничена.
Я действительно задавался вопросом, было ли получение значения хеша и присвоение его нормальной переменной каким-то образом автоматически декодировать или кодировать.Я не очень понимаю, когда Perl использует свой внутренний символьный формат, в отличие от того, когда он сохраняет внешнюю кодировку.
ОБНОВЛЕНИЕ С РЕШЕНИЕМ
Оказывается, поскольку строка, полученная из БД, уже находится вUTF-8, мне нужно использовать «to_json», а не «encode_json».Это решило проблему.Хотя много узнал об обработке Perl Unicode в процессе ...
Также рекомендую: http://perldoc.perl.org/perluniintro.html
Очень четкое изложение.