this questionおよびthis answer(他の質問への)に関連して、私はまだJSONでUTF-8を処理できません。perl:JSON文字列の不正な形式のUTF-8文字
私は、最高のエキスパートからの推薦に基づいて、必要なすべてのブードーが呼び出されていることを確認しましたが、文字列が有効であり、可能な限りUTF-8としてマークされ、ラベル付けされていることがわかります。しかし、まだのperl
Uncaught exception: malformed UTF-8 character in JSON string
または
Uncaught exception: Wide character in subroutine entry
のいずれかで死ぬ私はここで間違って何をしているのですか?これを実行する
(hlovdal) localhost:/work/2011/perl_unicode>cat json_malformed_utf8.pl
#!/usr/bin/perl -w -CSAD
### BEGIN ###
# Apparently the very best perl unicode boiler template code that exist,
# https://stackoverflow.com/questions/6162484/why-does-modern-perl-avoid-utf-8-by-default/6163129#6163129
# Slightly modified.
use v5.12; # minimal for unicode string feature
#use v5.14; # optimal for unicode string feature
use utf8; # Declare that this source unit is encoded as UTF‑8. Although
# once upon a time this pragma did other things, it now serves
# this one singular purpose alone and no other.
use strict;
use autodie;
use warnings; # Enable warnings, since the previous declaration only enables
use warnings qw< FATAL utf8 >; # strictures and features, not warnings. I also suggest
# promoting Unicode warnings into exceptions, so use both
# these lines, not just one of them.
use open qw(:encoding(UTF-8) :std); # Declare that anything that opens a filehandles within this
# lexical scope but not elsewhere is to assume that that
# stream is encoded in UTF‑8 unless you tell it otherwise.
# That way you do not affect other module’s or other program’s code.
use charnames qw<:full>; # Enable named characters via \N{CHARNAME}.
use feature qw<unicode_strings>;
use Carp qw< carp croak confess cluck >;
use Encode qw< encode decode >;
use Unicode::Normalize qw< NFD NFC >;
END { close STDOUT }
if (grep /\P{ASCII}/ => @ARGV) {
@ARGV = map { decode("UTF-8", $_) } @ARGV;
}
$| = 1;
binmode(DATA, ":encoding(UTF-8)"); # If you have a DATA handle, you must explicitly set its encoding.
# give a full stack dump on any untrapped exceptions
local $SIG{__DIE__} = sub {
confess "Uncaught exception: @_" unless $^S;
};
# now promote run-time warnings into stackdumped exceptions
# *unless* we're in an try block, in which
# case just generate a clucking stackdump instead
local $SIG{__WARN__} = sub {
if ($^S) { cluck "Trapped warning: @_" }
else { confess "Deadly warning: @_" }
};
### END ###
use JSON;
use Encode;
use Getopt::Long;
use Encode;
my $use_nfd = 0;
my $use_water = 0;
GetOptions("nfd" => \$use_nfd, "water" => \$use_water);
print "JSON->backend->is_pp = ", JSON->backend->is_pp, ", JSON->backend->is_xs = ", JSON->backend->is_xs, "\n";
sub check {
my $text = shift;
return "is_utf8(): " . (Encode::is_utf8($text) ? "1" : "0") . ", is_utf8(1): " . (Encode::is_utf8($text, 1) ? "1" : "0"). ". ";
}
my $json_text = "{ \"my_test\" : \"hei på deg\" }\n";
if ($use_water) {
$json_text = "{ \"water\" : \"水\" }\n";
}
if ($use_nfd) {
$json_text = NFD($json_text);
}
print check($json_text), "\$json_text = $json_text";
# test from perluniintro(1)
if (eval { decode_utf8($json_text, Encode::FB_CROAK); 1 }) {
print "string is valid utf8\n";
} else {
print "string is not valid utf8\n";
}
my $hash_ref1 = JSON->new->utf8->decode($json_text);
my $hash_ref2 = decode_json($json_text);
__END__
は
(hlovdal) localhost:/work/2011/perl_unicode>./json_malformed_utf8.pl
JSON->backend->is_pp = 0, JSON->backend->is_xs = 1
is_utf8(): 1, is_utf8(1): 1. $json_text = { "my_test" : "hei på deg" }
string is valid utf8
Uncaught exception: malformed UTF-8 character in JSON string, at character offset 20 (before "\x{5824}eg" }\n") at ./json_malformed_utf8.pl line 96.
at ./json_malformed_utf8.pl line 46
main::__ANON__('malformed UTF-8 character in JSON string, at character offset...') called at ./json_malformed_utf8.pl line 96
(hlovdal) localhost:/work/2011/perl_unicode>./json_malformed_utf8.pl | ./uniquote
Uncaught exception: malformed UTF-8 character in JSON string, at character offset 20 (before "\x{5824}eg" }\n") at ./json_malformed_utf8.pl line 96.
at ./json_malformed_utf8.pl line 46
main::__ANON__('malformed UTF-8 character in JSON string, at character offset...') called at ./json_malformed_utf8.pl line 96
JSON->backend->is_pp = 0, JSON->backend->is_xs = 1
is_utf8(): 1, is_utf8(1): 1. $json_text = { "my_test" : "hei p\N{U+E5} deg" }
string is valid utf8
(hlovdal) localhost:/work/2011/perl_unicode>./json_malformed_utf8.pl -nfd | ./uniquote
Uncaught exception: Wide character in subroutine entry at ./json_malformed_utf8.pl line 96.
at ./json_malformed_utf8.pl line 46
main::__ANON__('Wide character in subroutine entry at ./json_malformed_utf8.pl line 96.\x{a}') called at ./json_malformed_utf8.pl line 96
JSON->backend->is_pp = 0, JSON->backend->is_xs = 1
is_utf8(): 1, is_utf8(1): 1. $json_text = { "my_test" : "hei pa\N{U+30A} deg" }
string is valid utf8
(hlovdal) localhost:/work/2011/perl_unicode>./json_malformed_utf8.pl -water
JSON->backend->is_pp = 0, JSON->backend->is_xs = 1
is_utf8(): 1, is_utf8(1): 1. $json_text = { "water" : "水" }
string is valid utf8
Uncaught exception: Wide character in subroutine entry at ./json_malformed_utf8.pl line 96.
at ./json_malformed_utf8.pl line 46
main::__ANON__('Wide character in subroutine entry at ./json_malformed_utf8.pl line 96.\x{a}') called at ./json_malformed_utf8.pl line 96
(hlovdal) localhost:/work/2011/perl_unicode>./json_malformed_utf8.pl -water | ./uniquote
Uncaught exception: Wide character in subroutine entry at ./json_malformed_utf8.pl line 96.
at ./json_malformed_utf8.pl line 46
main::__ANON__('Wide character in subroutine entry at ./json_malformed_utf8.pl line 96.\x{a}') called at ./json_malformed_utf8.pl line 96
JSON->backend->is_pp = 0, JSON->backend->is_xs = 1
is_utf8(): 1, is_utf8(1): 1. $json_text = { "water" : "\N{U+6C34}" }
string is valid utf8
(hlovdal) localhost:/work/2011/perl_unicode>./json_malformed_utf8.pl -water --nfd | ./uniquote
Uncaught exception: Wide character in subroutine entry at ./json_malformed_utf8.pl line 96.
at ./json_malformed_utf8.pl line 46
main::__ANON__('Wide character in subroutine entry at ./json_malformed_utf8.pl line 96.\x{a}') called at ./json_malformed_utf8.pl line 96
JSON->backend->is_pp = 0, JSON->backend->is_xs = 1
is_utf8(): 1, is_utf8(1): 1. $json_text = { "water" : "\N{U+6C34}" }
string is valid utf8
(hlovdal) localhost:/work/2011/perl_unicode>rpm -q perl perl-JSON perl-JSON-XS
perl-5.12.4-159.fc15.x86_64
perl-JSON-2.51-1.fc15.noarch
perl-JSON-XS-2.30-2.fc15.x86_64
(hlovdal) localhost:/work/2011/perl_unicode>
uniquoteがhttp://training.perl.com/scripts/uniquote
Updateからです与える:ソリューションを強調表示するブライアンへ
感謝を。予想されるようになりました次のようなJSONに渡されようとしているもののためにすべての通常の文字列のjson_text
とjson_bytes
を使用するソースを更新すると動作します:
my $json_bytes = encode('UTF-8', $json_text);
my $hash_ref1 = JSON->new->utf8->decode($json_bytes);
私はJSONモジュールのドキュメントが極めてだと思うことを言わなければなりません不明瞭で部分的に誤解を招く。
"text"(少なくとも私にとって)というフレーズは文字列を意味します。 したがって、$perl_scalar = decode_json $json_text
を読むとき、私は を期待しています。json_textはUTF-8でエンコードされた文字列です。 ドキュメントを完全に再読しました。「decode_json ...はUTF-8(バイナリ)文字列を受け取り、UTF-8でエンコードされたJSONテキストである を解析しようとしています」しかし、それはまだ私の意見ではっきりしていません。いくつかの追加の非ASCII 文字を持つ言語を使用して、私の背景から
が、私はあなたが使用されているコード ページを推測しなければならなかった日に戻って覚えて、電子メールはちょうど 8ビット目のストリッピングすることにより、テキストを不自由に使用されます文字列の文脈における "バイナリ"は、7ビットASCIIドメイン外の文字を含む文字列 を意味しました。しかし、実際に は "バイナリ"とは何ですか?すべての文字列がコアレベルでバイナリではありませんか?
ドキュメントでは、「簡単かつ高速なインターフェイス(期待値/生成UTF-8)」と「正しいUnicode処理」が最初に指摘されています。バイトシーケンス。私は の著者に少なくともこれをもっと明確にするよう依頼します。
TomのUnicodeユーティリティは、[Unicode :: Tussle](http://search.cpan.org/dist/Unicode-Tussle)としても入手できます。 –