1 2 3 4 5 6 7 8 9 10
# utf-8 Oktetten sind korrekt my $r = {foo => "Fünf € Lösung"}; print JSON->new->utf8(1)->encode($r), "\n", JSON->new->utf8(0)->encode($r); __END__ {"foo":"Fünf € Lösung"} {"foo":"Fünf € Lösung"}
1 2 3 4 5 6 7 8 9 10 11
use utf8; my $r = {foo => "Fünf € Lösung"}; print JSON->new->utf8(1)->encode($r), "\n", JSON->new->utf8(0)->encode($r); Ausgabe: Wide character in print at C:\Dokumente und Einstellungen\rolf\Desktop\pack.pl line 20. {"foo":"Fünf € Lösung"} {"foo":"Fünf € Lösung"}
JSON->new->utf8(0)->encode($r);
1
2
3
4
5
use JSON;
use utf8;
my $r = {foo => "Fünf € Lösung"};
binmode STDOUT,':bytes';
print JSON->new->utf8(1)->encode($r),"\n";
1
2
3
4
5
use JSON;
use utf8;
my $r = {foo => "Fünf € Lösung"};
binmode STDOUT,':encoding(UTF-8)';
print JSON->new->utf8(0)->encode($r),"\n";
Quote- nein, das ist nicht blödsinning, sondern entweder falsch oder richtig, je nachdem, wie die Datei abgespeichert wurde.Ein use utf8 in das Script einzubauen ist da natürlich blödsinnig.
perl -e '$l=q(ö); print length $l,qq(\n)'
QuoteWas nach STDOUT geht, wird von Perls I/O-Layer so aus interner Darstellung in Bytes umgewandelt, wie man es ihm angeschafft hat. Und wenn man nichts explizit anweist, dann wirkt der Default-I/O-Layer, und der ist nicht UTF-8. Wenn man ein UTF-8-codiertes "ö" im Default-Encoding einliest und hinterher im Default-Encoding wieder ausgibt, dann liefert das ein UTF-8-codiertes "ö", weil das Default-Encoding Bytes liest und Bytes rausschreibt. Für Perl intern sind das zwei Bytes - und auch zwei Characters. Deswegen gehen solche Konstruktionen erst dann für alle sichtbar in die Hosen, wenn gleichzeitig "richtige" UTF-8-Characters verarbeitet werden sollen.Aber hier in diesem Fall gehen interne Angelegenheiten nach STDOUT was nicht sein darf.
QuoteAbsolut richtig. Das fängt aber schon bei der Quelldatei an, siehe oben.Handle kennen nämlich keine Kodierung, sondern nur noch Bytes.
print to_json($r),"\n"; # Aequivalent zu print JSON->new->utf8(0)->encode($r),"\n";
QuoteDer Witz ist der: Nach STDOUT o.a. Handle (Dateien) dürfen keine Strings ausgegeben werden. Aber: encode_json() macht ja genau das.
Quoteencode_json gibt gar nichts aus
QuoteEs konvertiert einen Perl-Skalar in eine UTF-8-codierte Bytewurst.
{"amt":"Fünf € Lösung"}
QuoteConverts the given Perl data structure to a UTF-8 encoded, binary string (that is, the string contains octets only).
Quoteja auch parallel eine Funktion to_json gibt, die nicht kodiert.
1 2 3 4 5 6 7
my $amt = "Fünf €"; my $r = {amt => $amt}; use bytes; print JSON::to_json($r), "\n", $amt; {"amt":"Fünf €"} Fünf €
2018-05-07T17:59:15 hajNun auch noch use bytes;? Da steht, nicht ohne Grund,
Use of this module for anything other than debugging purposes is strongly discouraged.
Ich geb's jetzt auf. Viel Glück weiterhin!
QuoteDESCRIPTION
The "use bytes" pragma disables character semantics for the rest of the
lexical scope in which it appears.
1 2 3 4 5 6 7 8 9
my $amt = "Fünf €"; my $r = {amt => $amt}; use bytes; print JSON::to_json($r), "\n", $amt; Ausgabe: {"amt":"Fünf €"} Fünf € # $amt OK
1 2 3 4 5 6 7
use strict; use warnings; use JSON; # Bytes für das € Zeichen # UTF-8 my $h = { euro => pack("CCC", 226, 130, 172)}; print encode_json($h); # Müll
1 2 3 4 5 6 7 8 9 10 11 12
use strict; use warnings; use JSON; use 5.010; # enable terminal's utf8 for me system("chcp 65001"); # UTF-8 my $h = { euro => pack("CCC", 226, 130, 172) }; say to_json($h);
2023-05-14T12:47:45 rostiDu kannst das andersrum sehen: Das { utf8 => 0 } beschreibt nicht Deinen Input, sondern ist die Verarbeitungsanweisung "Nicht nach utf8 konvertieren".Wenn ich mit obenstehender Hashref notiere: print to_json( $h, { utf8 => 0 } ); ist die Ausgabe korrekt aber der Code ist eben verwirrend um nicht zu sagen blödsinnig. Denn übergeben wurden ja ganz sicher die richtigen Bytes für ein utf-8-kodiertes Eurozeichen. utf8 => 0 => WTF.
2023-05-14T12:47:45 rostiJa. Das entspräche auch der generellen Empfehlung, Daten zum frühest möglichen Zeitpunkt zu decodieren. Denn es ist keineswegs selbstverständlich, dass die Daten alle in UTF-8-Codierung daherkommen. Ich hatte beruflich mit Langzeitarchiven zu tun, da sollten die Auswertungen "zeitgemäß" in UTF-8 kommen - aber die Ausgangsdaten waren in unterschiedlichen Codierungen. In den 1970ern gab es noch kein UTF-8...Wenn man also korrekt sein will und gleichermaßen einen verständlichen Code schreiben soll, müsste man für sämtliche Strings die an JSON übergeben werden die Kodierung einschalten.
2023-05-14T12:47:45 rostiWenn man die Bytes beibehält, riskiert man falsche Ergebnisse bei regulären Ausdrücken und anderen Perl-Funktionen. Sinnvoll ist es also.Ob das bei Datenstrukturen die mehrere tausend einzelne Strings beinhalten sinnvoll ist, sei mal dahingestellt ;)
Linux ?Zu JSON und Encoding: https://www.rfc-editor.org/rfc/rfc8259#section-8.1
2023-05-16T05:37:45 rostiDer ganze Zirkus und die Missverständnisse um UTF-8 entstehen nur dadurch daß Perlprogrammierer unter Zeichenkodierung 2 Dinge verstehenen müssen: Zeichenkodierung und Zeichenorientierung. Während die Bytefolge 226 130 172 zweifelsfei ein UTF-8-kodiertes Eurozeichen repräsentiert muß man dem Perlinterpreter mitteilen ob er diese Bytesequenz als Folge von 3 Bytes oder als 1 Zeichen betrachten soll, je nachdem was Perl damit machen soll. Außerhalb von Perl gibt es nur Bytesequenzen!