JSON问题的Perl编码

时间:2018-11-12 15:46:19

标签: json perl unicode

很抱歉,如果这是一个非常愚蠢的问题或已经在其他地方提出来。我正在读取一些JSON并在其上使用解码_json,然后从中提取文本并将其输出到文件中。

我的问题是Unicode字符在JSON中编码为例如\ u2019,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 :(得分:2)

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);

但是仅对数据进行解码就没有意义。

答案 1 :(得分:2)

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};
   }
}

箭头指向两个摘要之间的三个细微差别。


我做了很多清理。

  • 如果JSON中有换行符,则缺少local $/;
  • 请勿使用2-arg open
  • 不必使用全局变量。
  • 对变量使用更好的名称。 $data$json明显颠倒了,并且$file没有包含文件。
  • 限制变量的范围,尤其是当变量用完系统资源(例如文件句柄)时。
  • 使用:encoding(UTF-8)(标准编码)代替:encoding(utf8)(仅Perl使用的编码)。 :utf8更糟糕,因为它使用内部编码而不是标准编码,如果提供错误的输入,则可能导致标量损坏。
  • 摆脱用作哈希键的标识符周围的嘈杂引号。