在Perl中对UTF8字符串进行JSON编码/解码

3

我在命令行中传递了一个经 UTF-8 编码的字符串到 Perl 程序中:

> ./test.pl --string='ḷet ūs try ṭhiñgs'

看起来正确识别了该字符串:

use utf8;  

GetOptions(                                                                     
    'string=s' => \$string,                                                     
) or die;                                                                    
print Dumper($string);
print Dumper(utf8::is_utf8($string));                                           
print Dumper(utf8::valid($string));                                             

打印
$VAR1 = 'ḷet ūs try ṭhiñgs';
$VAR1 = '';
$VAR1 = 1;

当我将这个字符串存储到哈希表中并在其上调用encode_json时,该字符串似乎被再次编码,而to_json似乎有效(如果我正确读取输出的话)。
my %a = ( 'nāme' => $string ); # Note the Unicode character                                                 
print Dumper(\%a);
print Dumper(encode_json(\%a));                                                 
print Dumper(to_json(\%a));                                                     

打印

$VAR1 = {
          "n\x{101}me" => 'ḷet ūs try ṭhiñgs'
        };
$VAR1 = '{"nāme":"ḷet Å«s try á¹­hiñgs"}';
$VAR1 = "{\"n\x{101}me\":\"\x{e1}\x{b8}\x{b7}et \x{c5}\x{ab}s try \x{e1}\x{b9}\x{ad}hi\x{c3}\x{b1}gs\"}";

然而,用这两种方法将其转换回原始哈希似乎都不起作用,在这两种情况下,哈希和字符串都被破坏了:

print Dumper(decode_json(encode_json(\%a)));                                    
print Dumper(from_json(to_json(\%a)));    

打印
$VAR1 = {
           "n\x{101}me" => "\x{e1}\x{b8}\x{b7}et \x{c5}\x{ab}s try \x{e1}\x{b9}\x{ad}hi\x{c3}\x{b1}gs"
        };
$VAR1 = {
          "n\x{101}me" => "\x{e1}\x{b8}\x{b7}et \x{c5}\x{ab}s try \x{e1}\x{b9}\x{ad}hi\x{c3}\x{b1}gs"
        };

哈希查找 $a{'nāme'} 现在失败了。

问题:在Perl中,如何正确处理utf8编码、字符串和JSON的编码/解码?


从你的第一个 print Dumper(utf8::is_utf8($string)); 返回 '' 十分明显,该字符串未被识别为 UTF-8。 - jcaron
utf8::valid($string)返回True。 - Jens
@Jens 这并不是你所想的意思。 - Matt Jacob
@MattJacob:嗯...好的? :-) - Jens
@Jens 在这种情况下,“valid”意味着“一致”。它被标记为“INTERNAL”是有原因的。只是...不要使用它。 - Matt Jacob
1个回答

4
您需要对输入进行解码:
use Encode;

my $string;
GetOptions('string=s' => \$string) or die;
$string = decode('UTF-8', $string);

将所有内容综合起来,我们得到:

use strict;
use warnings;
use 5.012;
use utf8;

use Encode;
use Getopt::Long;
use JSON;

my $string;
GetOptions('string=s' => \$string) or die;
$string = decode('UTF-8', $string);

my %hash = ('nāme' => $string);
my $json = encode_json(\%hash);
my $href = decode_json($json);

binmode(STDOUT, ':encoding(utf8)');
say $href->{nāme};

例子:

$ perl test.pl --string='ḷet ūs try ṭhiñgs'
ḷet ūs try ṭhiñgs

请确保您的源文件实际上已被编码为UTF-8!


è؟™ه¹¶و²،وœ‰è§£ه†³from_jsonهگژé‌¢çڑ„ه“ˆه¸Œé—®é¢ک,وک¯هگ—ï¼ں - Jens
@Jens 不要使用 to_json/from_json。请改用 encode_json/decode_json 以保持 UTF-8 编码。 - Matt Jacob
那么我应该如何正确处理我的问题末尾的哈希查找呢? - Jens
谢谢!我看到你还添加了binmode - Jens
@Jens 是的,你需要对输出进行编码,这将自动为 STDOUT 完成。 - Matt Jacob
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接