perl: Uncaught exception: fehlerhafte UTF-8-Zeichen im JSON-string
Bezug auf diese Frage und diese Antwort (eine weitere Frage) ich bin immer noch nicht UTF-8 mit JSON.
Ich habe versucht, um sicherzustellen, dass alle erforderlichen voodoo ist aufgerufen, auf der Grundlage der Empfehlungen von die besten Experten, und soweit ich sehen kann, wird der string als gültig markiert und beschriftet, als UTF-8 möglich. Aber noch perl stirbt entweder
Uncaught exception: malformed UTF-8 character in JSON string
oder
Uncaught exception: Wide character in subroutine entry
Was mache ich hier falsch?
(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__
Ausgeführt dies gibt
(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 ist aus http://training.perl.com/scripts/uniquote
Update:
Danke an brian für die Hervorhebung der Lösung. Die Aktualisierung der Quelle zu verwenden json_text
für alle normalen strings und json_bytes
für das, was übergeben werden soll, um JSON wie folgt funktioniert jetzt wie erwartet:
my $json_bytes = encode('UTF-8', $json_text);
my $hash_ref1 = JSON->new->utf8->decode($json_bytes);
Muss ich sagen, dass ich denke, dass die Dokumentation für das JSON-Modul ist extrem unübersichtlich und teilweise irreführend.
Den Begriff "text" (zumindest für mich) bedeutet eine Zeichenkette.
Also beim Lesen $perl_scalar = decode_json $json_text
ich habe eine
Erwartung json_text ein UTF-8-codierte Zeichenfolge.
Gründlich Lesen Sie die Dokumentation, zu wissen, was zu suchen,
Ich sehe das jetzt sagt: "decode_json ... erwartet eine UTF-8 (Binär) ein string und versucht zu analysieren
dass ein UTF-8-codierte JSON-text", aber das ist immer noch nicht klar, meiner Meinung nach.
Meinem hintergrund in eine Sprache, mit einigen zusätzlichen non-ASCII
Zeichen, ich erinnere mich zurück in den Tagen, wo Sie zu erraten, den code
Seite verwendet wird, die E-Mail verwendet werden, um nur Krüppel text durch Strippen der
8 bit usw. Und "binary" im Kontext von strings gedacht, einen string
mit Zeichen außerhalb des 7-bit-ASCII-domain. Aber was ist
"binary" - wirklich? Nicht alle strings binäre auf die core-Ebene?
Die Dokumentation sagt auch "einfache und schnelle Schnittstellen (erwarten/erzeugen UTF-8)" und "richtigen unicode-handling", den ersten Punkt unter "Features", die beide ohne zu erwähnen, irgendwo in der Nähe, die es will nicht ein string sondern ein byte-Sequenz. Ich werde verlangen, dass die
Autor zumindest machen das deutlicher.
InformationsquelleAutor hlovdal | 2011-08-01
Du musst angemeldet sein, um einen Kommentar abzugeben.
Erweitere ich auf meine Antwort in Sie kennen den Unterschied zwischen Zeichen-strings und UTF-8-strings.
Vom Lesen der JSON-Dokumente, - ich denke, diejenigen Funktionen, die nicht wollen, eine Zeichenkette, aber das ist, was Sie versuchen, es zu geben. Stattdessen wollen Sie einen "UTF-8 Binär-string". Das scheint seltsam für mich, aber ich vermute, dass es hauptsächlich um die Eingabe direkt über eine HTTP-Nachricht, anstatt etwas, das Sie geben Sie direkt in Ihrem Programm. Dies funktioniert, da ich eine byte-Zeichenfolge, die die UTF-8-codierte version der Zeichenfolge:
Die Ausgabe zeigt, dass die Zeichenfolge nicht funktioniert, aber die byte-string-Version:
So, wenn Sie Ihre Zeichenfolge, die Sie eingegeben haben, direkt in das Programm und konvertieren Sie es in eine UTF-8-kodierten byte-string, funktioniert es:
Ich denke, JSON, sollte intelligent genug sein, um sich mit diesem, so dass Sie nicht haben, zu denken auf dieser Ebene, aber so ist es (bisher).
decode
.Re "ich denke, JSON, sollte intelligent genug sein, um damit umzugehen", ist es unmöglich. Es hat keine Möglichkeit zu wissen, ob etwas, das bereits entschlüsselt ist oder nicht.
Es scheint seltsam für mich, weil ich nicht erwarten, dass es. Ich möchte die Dinge einfach nur funktionieren, ohne diese Ebene des Denkens. Bei OSCON, mein Haupt-Kritikpunkt war, dass wir nur noch ein Skalar, und wir können nicht sagen, ob es ein Binär-string oder eine Zeichenkette. Für den smart genug, vielleicht ist es unmöglich, aber ich würde noch gerne diese Funktion. Ich Frage mich, was passiert wenn. Wenn Perl hat es gekennzeichnet als ein UTF-8 string, was ist wirklich mit JSON? Werde ich mal näher untersuchen.
Ich glaube nicht, dass es seltsam ist, zu Dekodieren, die etwas vor der übergabe an etwas namens decode(). Eine befasst sich mit der Zeichenkodierung, und beschäftigt sich mit der Daten-Struktur-Kodierung. Das sind unterschiedliche Tiere.
HTML5-details einen look-ahead-Ansatz. Nicht viel Wahl in der Angelegenheit, weil der Content-Type kann angezeigt werden, nachdem Sie gebraucht wird. Es ist immer noch als Teil des gleichen Prozess analysieren, aber.
InformationsquelleAutor brian d foy
Die docs sagen
doch Sie tun alles in Ihrer macht, Sie zu entschlüsseln, die Eingabe vor der übergabe an decode_json.
Ausgabe:
PS — Es wäre einfacher zu helfen, wenn Sie nicht über zwei Seiten code zu zeigen, ein einfaches problem.
InformationsquelleAutor ikegami
Ich glaube, dass ich zufällig über eine Antwort!
Es gibt eine Menge von Heimwerker-Bedarf. Hier sind meine IO-Befehle:
Dann auf JSON-decodieren-Sachen, die in die websocket:
Die hat nur mich geworfen, für eine Schleife, die ich vielleicht brauche Riechsalz!
Aber der einzige Weg, ich habe den Weg ganz frei für seltsame Symbole travelling disk - perl - websocket - /json - JS/HTML/Nutzung des Codemirror/was auch immer und wieder zurück. Die Symbole müssen auf den Datenträger geschrieben werden mit spurt, mit dem :utf8-level oder Modus. Ich denke, Mojo oder etwas, ich bin mit zusammen bricht, wie alles funktioniert in ein perl-one-liner, und ich weiß, dass ich es beheben kann, ich bin nur so goshdarn beschäftigt.
Gibt es wahrscheinlich etwas einfach irgendwo, aber ich bezweifle es. Leben überwältigt mich manchmal, ich erkläre!
Einer weniger Wahnsinn als diese Ergebnisse in gebrochene Charaktere auf der Festplatte, sondern arbeitet-Zeichen in perl und auf der anderen Ende der websocket.
InformationsquelleAutor Stuve Villge