Einzelnen Beitrag anzeigen

berens

Registriert seit: 3. Sep 2004
431 Beiträge
 
Delphi 2010 Professional
 
#1

lkJSON UTF-8 Problem üöä

  Alt 5. Dez 2016, 11:32
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
t := UTF8Decode(u); // bringt nix durch

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!
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit
  Mit Zitat antworten Zitat