【问题标题】:perl & python writing out non-ASCII characters into JSON differentlyperl & python 以不同方式将非 ASCII 字符写入 JSON
【发布时间】:2020-07-29 01:38:04
【问题描述】:

我有如下所示的哈希键:

1я310яHOM_REF_truth:HOM_ALT_test:discordant_hom_ref_to_hom_altяAяC

这是一个由西里尔字母 я 连接的字符串,我选择它作为分隔符,因为它永远不会出现在此文件中。

因此,我将其写入 Perl 5.30.2 中的 JSON 文件:

use JSON 'encode_json';

sub hash_to_json_file {
    my $hash     = shift;
    my $filename = shift;
    my $json = encode_json $hash;
    open my $out, '>', $filename;
    say $out $json
}

在 python 3.8 中:

use json
def hash_to_json_file(hashtable,filename):
    json1=json.dumps(hashtable)
    f = open(filename,"w+")
    print(json1,file=f)
    f.close()

当我尝试将 Python 编写的 JSON 加载回 Perl 脚本时,我看到一个我不知道如何解决的神秘错误:

Wide character in say at read_json.pl line 27.

阅读https://perldoc.perl.org/perlunifaq.html 我尝试将use utf8 添加到我的脚本中,但它不起作用。 我也在我的子例程中尝试了'>:encoding(UTF-8)',但同样的错误结果。

检查 JSON 文件后,我看到 "1Ñ180ÑHET_ALT_truth:HET_REF_test:discordant_het_alt_to_het_refÑAÑC,G" 之类的键,其中 ÑAÑ 替换了 я。在python写的JSON中,看到\u044f,我认为这是wide这个字符,但是不知道怎么改回来。

我也尝试过改变我的子程序:

use Encode 'decode';
sub json_file_to_hash {
   my $file = shift;
   open my $in, '<:encoding(UTF-8)', $file;
   my $json = <$in>;
   my $ref = decode_json $json;
   $ref = decode('UTF-8', $json);
   return %{ $ref }
}

但这给出了另一个错误:

Wide character in hash dereference at read_json.pl line 17, &lt;$_[...]&gt; line 1

如何将 python JSON 正确读入 Perl?

【问题讨论】:

    标签: json perl


    【解决方案1】:
    use utf8;                               # Source is encoded using UTF-8
    use open ':std', ':encoding(UTF-8)';    # For say to STDOUT.  Also default for open()
    
    use JSON qw( decode_json encode_json );
    
    sub hash_to_json_file {
        my $qfn = shift;
        my $ref = shift;
        my $json = encode_json($ref);       # Produces UTF-8
        open(my $fh, '>:raw', $qfn)         # Write it unmangled
           or die("Can't create \"$qfn\": $!\n");
    
        say $fh $json;
    }
    
    sub json_file_to_hash {
        my $qfn = shift;
        open(my $fh, '<:raw', $qfn)         # Read it unmangled
           or die("Can't create \"$qfn\": $!\n");
    
        local $/;                           # Read whole file
        my $json = <$fh>;                   # This is UTF-8
        my $ref = decode_json($json);       # This produces decoded text
        return $ref;                        # Return the ref rather than the keys and values.
    }
    
    my $src = { key => "1я310яHOM_REF_truth:HOM_ALT_test:discordant_hom_ref_to_hom_altяAяC" };
    hash_to_json("a.json", $src);
    my $dst = hash_to_json("a.json");
    say $dst->{key};
    

    您也可以通过使用from_jsonto_json 来避免使用:raw

    use utf8;                               # Source is encoded using UTF-8
    use open ':std', ':encoding(UTF-8)';    # For say to STDOUT. Also default for open()
    
    use JSON qw( from_json to_json );
    
    sub hash_to_json_file {
        my $qfn  = shift;
        my $hash = shift;
        my $json = to_json($hash);          # Produces decoded text.
        open(my $fh, '>', $qfn)             # "use open" will add :encoding(UTF-8)
           or die("Can't create \"$qfn\": $!\n");
    
        say $fh $json;                      # Encoded by :encoding(UTF-8)
    }
    
    sub json_file_to_hash {
        my $qfn = shift;
        open(my $fh, '<', $qfn)             # "use open" will add :encoding(UTF-8)
           or die("Can't create \"$qfn\": $!\n");
    
        local $/;                           # Read whole file
        my $json = <$fh>;                   # Decoded text thanks to "use open".
        my $ref = from_json($json);         # $ref contains decoded text.
        return $ref;                        # Return the ref rather than the keys and values.
    }
    
    my $src = { key => "1я310яHOM_REF_truth:HOM_ALT_test:discordant_hom_ref_to_hom_altяAяC" };
    hash_to_json("a.json", $src);
    my $dst = hash_to_json("a.json");
    say $dst->{key};
    

    【讨论】:

      【解决方案2】:

      我喜欢 ascii 选项,这样 JSON 输出都是 7 位 ASCII 码

      my $json = JSON->new->ascii->encode($hash);
      

      Perl 和 Python JSON 模块都可以读取它。

      【讨论】:

      • 1) 您建议使用 my $json = JSON-&gt;new-&gt;ascii-&gt;encode($hash); 替换 decode_json。那是行不通的。 2)-&gt;ascii在解码时没有效果。 3) 无法使用 ASCII 编码 1я310яHOM_REF_truth:HOM_ALT_test:discordant_hom_ref_to_hom_altяAяC。请记住,reader 不输出 JSON
      • 我建议在 hash_to_json_file 子例程中替换 encode_json
      • hash_to_json_file 工作正常。同样,OP 询问的错误来自程序 reading JSON。你的建议根本没有帮助。它只是使 JSON 变大而没有解决问题。
      猜你喜欢
      • 2014-04-04
      • 2014-04-05
      • 1970-01-01
      • 2016-12-09
      • 1970-01-01
      • 2016-11-20
      • 1970-01-01
      • 2014-06-01
      • 2016-01-20
      相关资源
      最近更新 更多