Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi lkJSON UTF-8 Problem üöä (https://www.delphipraxis.net/191069-lkjson-utf-8-problem-ueoeae.html)

berens 5. Dez 2016 11:32

lkJSON UTF-8 Problem üöä
 
Hallo,

ich habe das Problem, dass ich mit Delphi 2010 und Indy etwas heruntergeladen habe über idhttp.get. Der Inhalt ist laut Server-Betreiber UTF-8 codiert, also habe ich folgendes verwendet:

Delphi-Quellcode:
ssResult := TStringStream.Create('', TEncoding.UTF8);
idhttp.Get(_URL, ssResult);
Das Download-Ergebnis ist korrekt und komplett Menschenlesbar, d.h. wenn ich das Result in einem Memo anzeigen lasse, werden üöä richtig dargestellt.

Diesen String muss ich nun auch auswerten, da es sich hierbei um ein JSON handelt. Ich verwendet lkJSON mit Delphi 2010.

Zur Fehlersuche habe ich den problematischen String hier in die Konstante gespeichert.

Delphi-Quellcode:
procedure TForm2.Button3Click(Sender: TObject);
var
  i: integer;
  t: string;
  u: UTF8String;
  JSON_Document: TlkJSONbase;
  JSON_Element: TlkJSONbase;
  title: TlkJSONbase;
const
  JSONTEXT = '[{"id":270513903,"title":"Blättern"}]';
begin
  u := UTF8Encode(JSONTEXT);
  JSON_Document := TlkJSON.ParseText(u); // bis hier ist in Variable u "Blättern" noch korrekt in der "Liste der überwachten Ausdrücke" zu sehen

  for i := 0 to JSON_Document.Count - 1 do begin
    JSON_Element := JSON_Document.Child[i];
    if assigned(JSON_Element) then begin
      title := JSON_Element.Field['title'];
      if assigned(title) then begin
        u := title.Value; // u und title.Value halten nun 'Bl�ttern' bzw. 'Bl?ttern' #3F74
        t := UTF8Decode(u); // bringt nix
        if copy(t, 3, 1) <> 'ä' then begin
          // FEHLER
          sleep(0); // für BreakPoint
        end;
      end;
    end;
  end;
end;
Innerhalb von lkJSON entsteht das Problem an dieser Stelle:
Delphi-Quellcode:
    js := TlkJSONstring.Create;
{$ifdef USE_D2009}
    js.FValue := UTF8ToString(ws); // auch bei meinem Delphi 2010 wird diese Zeile verwendet
{$else}
    js.FValue := UTF8Decode(ws);
{$endif}
Hier wird aus dem lesbaren Text der Datenmüll.

EDIT: Wenn ich nun in dem o.g. Beispiel
Delphi-Quellcode:
t := UTF8Decode(u); // bringt nix
durch

Delphi-Quellcode:
t := UTF8ENCODE(u);
funktioniert es korrekt, also machen beide Funktionen gerade das Gegenteil von dem, was der Name sagt, bzw. ich von Ihnen erwarte?

"u" ist ja UTF8 codiert.
"t" ist nicht UTF8 codiert und bietet auch als Variable nur ein Byte pro Zeichen (?)
Jetzt speichere ich in "t" etwas rein was die Variable speichermäßig gar nicht aufnehmen kann, und kodiere einen UTF8-String erneut zu UTF8 damit es auch wirklich klappt? Ich bin verwirrt.

Ok, jetzt mal ernsthaft:
Wahrscheinlich sind in Delphi 2010 eh alle "string"-Variablen längt Multibyte, können also von Haus aus UTF8 speichern, und der Datentyp "UTF8String" ist veraltet oder wird nur für explizite Sonderfälle benötigt.
JSON hat wohl die Sonderzeichen zwar im MultiByte-Format zurückgegeben, aber die "Markierung" DASS es MultiByte oder was-auch-immer ist hat wohl gefehlt, so dass die UTF8-Bytes #3F74 als 2 Bytes eines Nicht-MultiByte-Strings interpretiert wurden. Warum!?
Durch das erneute Encodieren als UTF8 wurde diese "Markierung" wieder hergestellt und Delphi ist flexibel genug, um die Sonderzeichen auch dann korrekt in einem "normalen" string darzustellen, wenn dieser nicht Explizit von UTF8 nach ANSI oder UNICODE zurückgewandelt wurde.

Das eigentliche Problem ist also schon vor dem Absenden dieses Posts gelöst,
aber vielleicht helfen ja meine Gedankengänge jemandem mit dem selben Problem weiter (Speziell: Indy + JSON + UFT8 --> TStringStream.Create('', TEncoding.UTF8) !!), und vielleicht kann mir jemand noch 1-2 Sätze dazu sagen, weshalb das mit UTF8Decode/UTF8Encode für mich aktuell nicht ganz nachvollziehbar ist...

Danke, lg!

Stevie 5. Dez 2016 11:53

AW: lkJSON UTF-8 Problem üöä
 
Schaut so aus, als ob die Person, die diese Unit für Delphi 2009 und höher portiert hat, keine Ahnung hatte (siehe auch die vielen Warnings, die der Compiler für die Unit wirft - ich hab grad v1.07 gezogen). Für mich sieht das so aus, als ob er annimmt, dass ein UTF8 String als UnicodeString gespeichert wird (also für ein ü 2 Unicode Zeichen verbraucht werden - analog wie es vor Delphi 2009 in einem UTF8 kodierten AnsiString der Fall war (siehe Warning W1058 an von dir bereits genannten Stelle - Zeile 1883).

Im übrigen nimmt die ParseText Methode schon den falschen Datentyp entgegen - wurde vermutlich auch nicht bei der Umstellung berücksichtigt (siehe W1057 in der entsprechenden Stelle - Delphi führt dort eine automatische UTF8->UnicodeString konvertierung durch)

Und nein, UTF8String ist nicht veraltet ...

berens 5. Dez 2016 12:46

AW: lkJSON UTF-8 Problem üöä
 
Danke Stevie für die Antwort.

Ok, also dann doch ein Fehler von den JSON Komponenten.

Ich nehme an, wer von Euch mit JSON arbeitet hat eine neuere Version von Delphi, wo JSON ab Werk mitgeliefert mit?

Gibt es alternativ eine (kommerzielle) JSON Komponente die Delphi 2010 kompatibel ist und eine wenig höhere "Qualität" hat?

[Ich will auf keinen Fall undankbar sein, lkJSON ist ansonsten echt Klasse...]

Stevie 5. Dez 2016 14:28

AW: lkJSON UTF-8 Problem üöä
 
https://github.com/ahausladen/JsonDataObjects

DeddyH 5. Dez 2016 15:37

AW: lkJSON UTF-8 Problem üöä
 
Oder SuperObject


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:46 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz