Perl的JSON :: XS没有正确编码UTF8?

Omo*_*tis 7 perl json cgi

这个简单的代码段显示了我在Perl中使用JSON :: XS编码的问题:

#!/usr/bin/perl
use strict;
use warnings;
use JSON::XS; 
use utf8;
binmode STDOUT, ":encoding(utf8)";

my (%data);

$data{code} = "Gewürztraminer";
print "data{code} = " . $data{code} . "\n";

my $json_text = encode_json \%data;
print $json_text . "\n";
Run Code Online (Sandbox Code Playgroud)

产生的输出是:

johnnyb@boogie:~/Projects/repos > ./jsontest.pl 
data{code} = Gewürztraminer
{"code":"Gewürztraminer"}
Run Code Online (Sandbox Code Playgroud)

现在,如果我注释掉上面的binmode行,我得到:

johnnyb@boogie:~/Projects/repos > ./jsontest.pl 
data{code} = Gew?rztraminer
{"code":"Gewürztraminer"}
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?请注意,我正在尝试在不能使用binmode的perl CGI脚本中修复此行为,但我总是在JSON流中返回上面返回的"¼"字符.我该如何调试?我错过了什么?

ike*_*ami 11

encode_json(缩写JSON::XS->new->utf8->encode)使用UTF-8 进行编码,然后通过将其打印到已添加编码层的STDOUT进行重新编码.实际上,你正在做encode_utf8(encode_utf8($uncoded_json)).

解决方案1

use open ':std', ':encoding(utf8)';  # Defaults
binmode STDOUT;                      # Override defaults
print encode_json(\%data);
Run Code Online (Sandbox Code Playgroud)

解决方案2

use open ':std', ':encoding(utf8)';    # Defaults
print JSON::XS->new->encode(\%data);   # Or to_json from JSON.pm
Run Code Online (Sandbox Code Playgroud)

解决方案3

通过\u对非ASCII 使用转义,以下内容适用于STDOUT上的任何编码:

print JSON::XS->new->ascii->encode(\%data);
Run Code Online (Sandbox Code Playgroud)

在评论中,你提到它实际上是一个CGI脚本.

#!/usr/bin/perl
use strict;
use warnings;

use utf8;                      # Encoding of source code.
use open ':encoding(UTF-8)';   # Default encoding of file handles.
BEGIN {
   binmode STDIN;                       # Usually does nothing on non-Windows.
   binmode STDOUT;                      # Usually does nothing on non-Windows.
   binmode STDERR, ':encoding(UTF-8)';  # For text sent to the log file.
}

use CGI      qw( -utf8 );
use JSON::XS qw( ); 

{
   my $cgi = CGI->new();
   my $data = { code => "Gewürztraminer" };
   print $cgi->header('application/json');
   print encode_json($data);
}
Run Code Online (Sandbox Code Playgroud)

  • @Omortis CGI.pm不会发送任何东西.你的代码需要`print`东西.CGI.pm只是为您提供了为您生成HTML的旧功能.还要记住,CGI.pm不再是核心.:) (2认同)