Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Replace JSON Escape Steuerzeichen (https://www.delphipraxis.net/203746-replace-json-escape-steuerzeichen.html)

t2000 19. Mär 2020 09:48

Replace JSON Escape Steuerzeichen
 
Ist das hier die richtige Stelle im Forum?
Soll einfach nur ein Tipp sein.

Ich bekomme über eine REST-Schnittstelle JSON Daten mit Escape-Steuerzeichen. Diese muss ich rausfiltern, bzw. ersetzen.
Da ich nichts gefunden habe, hier meine Routine.

Falls jemand auch sowas sucht

Delphi-Quellcode:
function ReplaceJSONEscape( JSONString: String): String;
// Backslash's ohne richtigen Code bleiben im Text erhalten
var
  p1: Integer;
  l: Integer;
  i: Integer;
  c: Char;  // = WideChar
begin
  result := JSONString;
  p1 := pos('\', JSONString);
  l := length(JSONString);
  if (p1 = 0) or (p1 = l) then
    exit;
  c := JSONString[p1+1];
  case c of
    '"' : result := copy( JSONString, 1, p1-1) + '"' + ReplaceJSONEscape( copy( JSONString, p1+2, l-p1-2));
    '\' : result := copy( JSONString, 1, p1-1) + '\' + ReplaceJSONEscape( copy( JSONString, p1+2, l-p1-2));
    '/' : result := copy( JSONString, 1, p1-1) + '/' + ReplaceJSONEscape( copy( JSONString, p1+2, l-p1-2));
    'b' : result := copy( JSONString, 1, p1-1) +  #8 + ReplaceJSONEscape( copy( JSONString, p1+2, l-p1-2));
    'f' : result := copy( JSONString, 1, p1-1) + #12 + ReplaceJSONEscape( copy( JSONString, p1+2, l-p1-2));
    'n' : result := copy( JSONString, 1, p1-1) + #10 + ReplaceJSONEscape( copy( JSONString, p1+2, l-p1-2));
    'r' : result := copy( JSONString, 1, p1-1) + #13 + ReplaceJSONEscape( copy( JSONString, p1+2, l-p1-2));
    't' : result := copy( JSONString, 1, p1-1) +  #9 + ReplaceJSONEscape( copy( JSONString, p1+2, l-p1-2));
    'u' : begin
            if l < (p1+5) then
              exit;
            i := StrToIntDef('$' + copy( JSONString, p1+2, 4), 0);
            if i = 0 then
              exit;
            result := copy( JSONString, 1, p1-1) + char(i) + ReplaceJSONEscape( copy( JSONString, p1+6, l-p1-6));
          end
    else
      result := copy( JSONString, 1, p1) +  ReplaceJSONEscape( copy( JSONString, p1+1, l-p1-1));
  end; // case
end;

Neutral General 19. Mär 2020 10:04

AW: Replace JSON Escape Steuerzeichen
 
Alternativ könntest du auch ne JSON Klasse benutzen (System.JSON - TJSONObject etc) die dir das intern alles schon abnimmt und du dir überhaupt keine Gedanke um sowas machen musst.
Sowas ist die halbe Garantie dass irgendwann irgendwas nicht funktioniert.

t2000 19. Mär 2020 10:37

AW: Replace JSON Escape Steuerzeichen
 
Das wollte ich ja, aber unter Delphi habe ich nichts gefunden, was die Steuerzeichen entfernt oder mir daraus ein TJSONObject macht. Wenn es da etwas gibt, dann sag es mir bitte.
Ich nutze intern NUR TJSONObject. Bekomme aber einen String mit Steuerzeichen geliefert.

t2000 19. Mär 2020 10:57

AW: Replace JSON Escape Steuerzeichen
 
Vielleicht habe ich aber auch ein Fehler gemacht.

Wenn ich den Umweg über einen String gehe, kann ich mir die eigene Routine sparen.
Das erste Beispiel erzeugt eine Exception, aber das zweite Beispiel funktioniert.
Aber einen direkten weg das Object zu erzeugen habe ich nicht gefunden.

Delphi-Quellcode:
// Übergabe an diese Funktion AParam bzw. LParam : TJSONObject;
var
  FJSONData      : TJSONObject;
  FJSONDataString : String;
begin
  // ****** Exception
  FJSONData   := LParam.GetValue<TJSONObject>( sngTypeJSONName_Parameter_JSONData); //  Das verursacht eine Exception weil ein "-Zeichen mit einem Steuerzeichen versehen ist: Exception bei \"
  // *******

  FJSONDataString := LParam.GetValue<string>( sngTypeJSONName_Parameter_JSONData);  // Das funktioniert und die Backslashs sind weg
  //FJSONDataString := ReplaceJSONEscape(FJSONDataString);   // Dies ist also nicht notwendig
  FJSONData   := TJSONObject.ParseJSONValue( FJSONDataString) as TJSONObject;  // und hier erzeuge ich mein TJSONObject

Uwe Raabe 19. Mär 2020 11:38

AW: Replace JSON Escape Steuerzeichen
 
Kannst du mal ein Beispiel mit konkreten Daten geben? Insbesondere, wie wird LParam mit was gefüllt und was steht in sngTypeJSONName_Parameter_JSONData?

t2000 19. Mär 2020 16:13

AW: Replace JSON Escape Steuerzeichen
 
Klar, hier mal ein konkretes Beispiel:

Ich nutze TMS XData Framework für meine REST Kommunikation
Auf Serverseite habe ich folgende REST-Funktion

Delphi-Quellcode:
function TMeineFunc.CheckSvcRunning(const Param: TJSONObject) : TJSONObject;
Diese wird aufgerufen und von dort möchte ich als erstes den Parameter überprüfen und in mein eigenes TsngParameter-Object überführen.
Ich rufe also die Create-Routine direkt mit den erhaltenen Daten auf.

Die Daten lauten (Beispiel) STRG-F7 -> AParam.toString ->
'{"Function":"CheckSvcRunning","Version":"10000"," Data":"{\"Services\":[\"75CBA3B2-0970-4278-9170-AEE6920587B1\",\"75CBA3B2-0970-4278-9170-AEE6920587B1\"]}"}'

Die Funktion sollte das gleiche Ergebnis liefern, wenn die gesamten Daten nochmals in {"Param":{...}} gekapselt wären. Daher die ersten Zeilen im Create Constructor

Man sieht, dass das interne Objekt die Backslashes hat. Die direkte Erstellung hat die Exception geliefert. Der Umweg über den String funktioniert aber.

Hier nochmal der ganze Code:

Delphi-Quellcode:
const
  sngType_ExceptionResult = 'Exception';
  sngTypeJSONName_Parameter            = 'Param';
  sngTypeJSONName_Parameter_sngFunction = 'Function';
  sngTypeJSONName_Parameter_Version    = 'Version';
  sngTypeJSONName_Parameter_JSONData   = 'Data';

constructor TsngParameter.Create( const AParam: TJSONObject);
var
  LParam: TJSONObject;
  FJSONDataString: String;
begin
  try
    // Wenn das JSON in einem Parameter-Feld enthalten ist, dann auspacken, falls nicht, direkt zugreifen
    if AParam.GetValue( sngTypeJSONName_Parameter) <> nil then
      LParam := AParam.GetValue<TJSONObject>( sngTypeJSONName_Parameter)
    else
      LParam := AParam;

    FsngFunction := LParam.GetValue<string>( sngTypeJSONName_Parameter_sngFunction);
    FVersion    := LParam.GetValue<string>( sngTypeJSONName_Parameter_Version);
    SetVersionCode(FVersion);

    //FJSONData   := LParam.GetValue<TJSONObject>( sngTypeJSONName_Parameter_JSONData); Exception bei \"
    FJSONDataString := LParam.GetValue<string>( sngTypeJSONName_Parameter_JSONData);
    //FJSONDataString := ReplaceJSONEscape(FJSONDataString);   nicht notwendig
    FJSONData   := TJSONObject.ParseJSONValue( FJSONDataString) as TJSONObject;

  except
    on e: Exception do begin
      FsngFunction := sngType_ExceptionResult;
      FVersion    := e.Message;
      FJSONData   := nil;
    end;
  end;
end;

Uwe Raabe 19. Mär 2020 16:27

AW: Replace JSON Escape Steuerzeichen
 
OK, der Wert in "Data" ist in diesem Fall tatsächlich ein String und kein JSON Objekt, sonst würde er nicht in Anführungszeichen stehen. Insofern ist der Umweg über String notwendig.

himitsu 19. Mär 2020 16:48

AW: Replace JSON Escape Steuerzeichen
 
Nur bedingt, zumindestens nicht als String, den man komplett manuell beackert.

Ein JSON-Object aus diesem String erstellen und darüber den Wert abzulesen ist schon gut.
Wobei man sich auch überlegen könnte, warum das ein String ist und nicht direkt als Subobject.
Code:
'{"Function":"CheckSvcRunning","Version":"10000","Data":{"Services":["75CBA3B2-0970-4278-9170-AEE6920587B1","75CBA3B2-0970-4278-9170-AEE6920587B1"]}}'
Also ob man den "Makel" hier nicht besser auf Seite des Senders schon beheben könnte.

Zitat:

Delphi-Quellcode:
" Data":

Wollte erst fragen, ob da beim Data wirlich ein Leerzeichen ist, aber das hat's Forum da reingeschmugglt. :stupid:

t2000 19. Mär 2020 17:28

AW: Replace JSON Escape Steuerzeichen
 
Zitat:

Zitat von himitsu (Beitrag 1460147)
...Also ob man den "Makel" hier nicht besser auf Seite des Senders schon beheben könnte.

Ich sende selber. Ein korrektes TJSONObject. Aber das muss wohl irgendwo im TMS XData so konvertiert werden.
Aber mit der Funktion bin ich auf der sicheren Seite, falls ich den Server für fremde Entwicker freigebe. Und wer weiß, wie andere "Sender" hier Daten verschicken.
Ich bin ja schon froh, das es doch recht einfach alles funktioniert. Und ich kann mit dem RESTED Plugin mit Firefox oder Chrome wirklich sehr gut (mal eben) testen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:59 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