Perl-кодировка из выпуска JSON - PullRequest
0 голосов
/ 12 ноября 2018

извиняюсь, если это действительно глупый вопрос или уже задавался в другом месте. Я читаю какой-то JSON и использую для него decode_json, затем извлекаю из него текст и выводю его в файл.

Моя проблема заключается в том, что символы Unicode кодируются как, например, \ u2019 в JSON, появляется decode_json, чтобы преобразовать это в \ x {2019}. Когда я беру этот текст и выводлю его в файл в кодировке UTF8, он выглядит как мусор.

Пример кода:

use warnings;
use strict;
use JSON qw( decode_json );
use Data::Dumper;

open IN, $file or die;
binmode IN, ":utf8";
my $data = <IN>;
my $json = decode_json( $data );
open OUT, ">$outfile" or die;
binmode OUT, ":utf8";
binmode STDOUT, ":utf8";
foreach my $textdat (@{ $json->{'results'} }) {
    print STDOUT Dumper($textdat);
    my $text = $textdat->{'text'};
    print OUT "$text\n";
}

Вывод Dumper показывает, что кодировка \ u была преобразована в кодировку \ x. Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018

decode_json ожидает UTF-8, но вместо этого вы передаете декодированный текст (кодовые точки Unicode).

Таким образом, вы можете удалить существующее декодирование символов.

use feature qw( say );
use open 'std', ':encoding(UTF-8)';
use JSON qw( decode_json );

my $json_utf8 = do {
   open(my $fh, '<:raw', $in_qfn)
      or die("Can't open \"$in_qfn\": $!\n");

   local $/;
   <$fh>;
 };

my $data = decode_json($json_utf8);

{
   open(my $fh, '>', $out_qfn)
      or die("Can't create \"$out_qfn\": $!\n");

   for my $result (@{ $data->{results} }) {
      say $fh $result->{text};
   }
}

Или вы можете использовать from_json (или JSON->new->decode) вместо decode_json.

use feature qw( say );
use open 'std', ':encoding(UTF-8)';
use JSON qw( from_json );                         # <---

my $json_ucp = do {
   open(my $fh, '<', $in_qfn)                     # <---
      or die("Can't open \"$in_qfn\": $!\n");

   local $/;
   <$fh>;
 };

my $data = from_json($json_ucp);                  # <---

{
   open(my $fh, '>', $out_qfn)
      or die("Can't create \"$out_qfn\": $!\n");

   for my $result (@{ $data->{results} }) {
      say $fh $result->{text};
   }
}

Стрелки указывают на три незначительных различия между двумя фрагментами.


Я сделал несколько чисток.

  • Отсутствует local $/; на случай, если в JSON есть разрывы строк.
  • Не используйте 2-arg open.
  • Не используйте ненужные глобальные переменные.
  • Используйте более подходящие имена для переменных.$data и $json были значительно изменены, а $file не содержал файла.
  • Ограничьте область действия ваших переменных, особенно если они используют системные ресурсы (например, дескрипторы файлов).
  • Используйте :encoding(UTF-8) (стандартная кодировка) вместо :encoding(utf8) (кодировка, используемая только Perl).:utf8 еще хуже, поскольку он использует внутреннюю кодировку, а не стандартную, и может привести к повреждению скаляров при неправильном вводе.
  • Избавиться от зашумленных кавычек вокруг идентификаторов, используемых в качестве хэш-ключей.
0 голосов
/ 12 ноября 2018

decode_json требуется вход в кодировке UTF-8, поэтому используйте вместо него from_json, который принимает Unicode:

my $json = from_json($data);

Другой вариант - это кодировать данные самостоятельно:

use Encode;

my $encoded_data = encode('UTF-8', $data);
...
my $json = decode_json($data);

Но бессмысленно кодировать данные только для их декодирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...