Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   DataSnap ein TFDJSONDataSets als TJSONObject übertragen (https://www.delphipraxis.net/184418-datasnap-ein-tfdjsondatasets-als-tjsonobject-uebertragen.html)

Kostas 25. Mär 2015 10:40

Datenbank: Firebird • Version: 2.5 • Zugriff über: DataSnap

DataSnap ein TFDJSONDataSets als TJSONObject übertragen
 
Hallo Zusammen,

sorry für den unglückliche Titel.

Ich habe einen DataSnap Server. Mittels FireDac wird ein DataSet als TFDJSONDataSets
bereitgestellt. Ein Mobile RESTClient ruft das DataSet ab und befüllt damit eine TFDMemTable.
Das funktioniert einwandfrei und sehr stabil.

Die Kommunikation läuft über HTTP Port 8080. Ich versuche den Server zu erweitern so dass ich die gleiche
DataSets konsumieren kann diesmal über TCP/IP Port 211. Soweit ich es richtig verstanden habe, kann ein
TFDJSONDataSets nur über TDSRestConnection transportiert werden und nicht über eine TSQLConnection.
Deshalb versuche ich gerade TFDJSONDataSets umzuwandeln in ein TJSONObject um es über TSQLConnection
zu transportieren. Ein reines TJSONObject hätte auch den Vorteil dass ich es als Log in Klartext zwischenspeichern könnte!


Der Client bekommt beim abrufen eine Fehlermeldung:
Im Projekt ist eine Exception der Klasse TDBXError mit der Meldung 'Exception: '{' found:
',' at Position: 23
{"result":[{"rows":[0]},{"data":[12,#192*Connection]}]' aufgetreten.



So gehe ich vor:

Delphi-Quellcode:
//Der Server exportier die Query als TFDJSONDataSets
function TdmDALZMI.GetBau(BauNr:integer): TFDJSONDataSets;
begin
  qrGetBau.Active := False;
  qrGetBau.Params[0].Value := BauNr;

  Result := TFDJSONDataSets.Create;
  TFDJSONDataSetsWriter.ListAdd(Result, qrGetBau);
end;

//Der Server gibt die gleiche Query als TJSONObject aus.
function TdmDALZMI.GetBauJSON(BauNr:integer): TJSONObject;
var
  LDataSets: TFDJSONDataSets;
begin
  LDataSets := GetBau(BauNr);
  try
    Result := TJSONObject.Create;
    TFDJSONInterceptor.DataSetsToJSONObject(LDataSets, Result); <<<<<<<<<< Ist das hier richtig?
  finally
    LDataSets.Free;
  end;
end;


//Der Client ruft das DataSet als TJSONObject ab und wandelt es in ein TFDJSONDataSets um
procedure TdmZMI.GetBauJSON(BauNr:integer);
var
  LDataSetList: TFDJSONDataSets;
  LJSONObject: TJSONObject;
  LZMIClient: TdmServerMethodsZMIClient;

begin
  LZMIClient := TdmServerMethodsZMIClient.Create(CMClientModule.CMCSQLConnection.DBXConnection);
  try
    LJSONObject := LZMIClient.ZMI_GetBauJSON(BauNr); <<<<<<<<<< Fehlermeldung an dieser Stelle
    TFDJSONInterceptor.JSONObjectToDataSets(LJSONObject,LDataSetList);
  finally
    LZMIClient.Free;
  end;

  UpdateMemTable(mtBau, LDataSetList);
  mtBau.Open;
end;

//Der Client befüllt aus dem TFDJSONDataSets eine TFDMemTable
procedure TdmZMI.UpdateMemTable(const aMemTable:TFDMemTable; const ADataSetList: TFDJSONDataSets);
begin
  aMemTable.Active := False;
  Assert(TFDJSONDataSetsReader.GetListCount(ADataSetList) = 1);
  aMemTable.AppendData(TFDJSONDataSetsReader.GetListValue
    (ADataSetList, 0));

end;
Hat jemand eine Idee wo denn das Problem sein könnte oder gibt es eine einfachere Art eine
FireDac Query als TJSONObject an den Client über TCP(nicht HTTP) zu übertragen und dort
auf einfache weise ebenfalls mit FireDac zu konsumieren?


Herzlichen Dank für die Hilfe.
Gruß Kostas

Mavarik 25. Mär 2015 10:46

AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
 
Zitat:

Zitat von Kostas (Beitrag 1294747)
FireDac Query als TJSONObject an den Client über TCP(nicht HTTP) zu übertragen und dort
auf einfache weise ebenfalls mit FireDac zu konsumieren?

Warum willst Du aus dem Query erst ein JSONObject machen?

Wir reden hier doch von "Select * from Datenbank where Name Like "Per%" order by Name Limit 100"
oder so?

Übertrag das doch einfach als String...

Oder übersehe ist gerade etwas?

Mavarik

Der schöne Günther 25. Mär 2015 10:49

AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
 
Er meint nicht den Query-String, sondern das aus der Query resultierende TDataSet.

Mavarik 25. Mär 2015 10:54

AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1294750)
Er meint nicht den Query-String, sondern das aus der Query resultierende TDataSet.

Ahh ok... Hatte ich dann doch etwas übersehen...

Kostas 25. Mär 2015 10:56

AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
 
Hallo Mavarik,

ich möchte gerne jedes DataSet welches zum Client übertragen wird als TJSONObject
(String Klartext) separat zwischenspeichern. Der Hintergrund, es gibt Gruppen von Clients.
Wenn ein Teilnehmer einer Gruppe ein Paket anfordert, muss dieses Paket auch an alle
anderen Clients dieser Gruppe vorgehalten werden bis sie sich anmelden. Danach bekommen sie
die Pakete automatisch übertragen. TJSONObject ist schlank und lässt sich dadurch gut zwischenspeichern.

Sicherlich ist nur eine Kleinigkeit falsch, auf die ich nicht komme.
Wenn es jedoch eine bessere Möglichkeit gibt wie du schon sagtest einfach das Result eines Select
als TJSONObject zu exportieren, zwischenspeichern und zum Client zu transportieren, bin ich da sehr offen
dafür.

Gruß Kostas

Mavarik 25. Mär 2015 11:03

AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
 
Zitat:

Zitat von Kostas (Beitrag 1294755)
ich möchte gerne jedes DataSet welches zum Client übertragen wird als TJSONObject
(String Klartext) separat zwischenspeichern.

Ich komme - wahrscheinlich in 4 Wochen - auch zu dieser Stelle... Also durchaus interessant...

Kostas 25. Mär 2015 14:03

AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
 
Ich habe etwas feststellen können.
Wenn ich die Query per SaveToFile als Jason exportiere, bekomme ich ein sauberes JASON.
Der TFDJSONDataSetsWriter erzeugt ein binäres Format.

könnte hier das Problem sein?

Delphi-Quellcode:
function TdmDALZMI.GetBau(BauNr:integer): TFDJSONDataSets;
begin
  qrGetBau.Active := False;
  qrGetBau.Params[0].Value := BauNr;
  qrGetBau.Active := True;
  qrGetBau.SaveToFile('f:\JSONBau.txt',TFDStorageFormat.sfJSON);  <<< String Klartext

  Result := TFDJSONDataSets.Create;
  TFDJSONDataSetsWriter.ListAdd(Result, qrGetBau);
end;


function TdmDALZMI.GetBauJSON(BauNr:integer): TJSONObject;
var
  LDataSets: TFDJSONDataSets;
  s:TStringList;
begin
  LDataSets := GetBau(BauNr);
  try
    Result := TJSONObject.Create;
    TFDJSONInterceptor.DataSetsToJSONObject(LDataSets, Result);

    s:=TStringList.Create;
    s.Text := result.ToString;
    s.SaveToFile('f:\JSON.txt'); <<<<< Binärer Inhalt
    s.Free;


  finally
    LDataSets.Free;
  end;
end;

Gruß Kostas

Uwe Raabe 25. Mär 2015 14:29

AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
 
Zitat:

Zitat von Kostas (Beitrag 1294795)
Wenn ich die Query per SaveToFile als Jason exportiere, bekomme ich ein sauberes JASON.
Der TFDJSONDataSetsWriter erzeugt ein binäres Format.

Das ist richtig, aber es erklärt jetzt nicht so offensichtlich die Fehlermeldung.

Allerdings kannst du über SaveToStream die Query in einen TStringStream schreiben, den String übertragen und dann ebenfalls über TStringStream und LoadFromStream das DataSet wieder aufbauen. Ist nur ein Workaround - falls es eilig ist.

Kostas 25. Mär 2015 14:47

AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
 
Hallo Uwe,

ich hatte gehofft dass du als Experte mein Thread liest. :-)

Ok, mein Vorgehen scheint also richtig zu sein.
Auf mein DataModul hatte ich ein FDStanStorageJSONLink1 und eine FDStanStorageBinLink1 die Bin Version habe ich entfernt, doch leider kein Unterschied.

Müsste das hier nicht wieder ein normales lesbares JASON erzeugen,
oder ist es normal dass das JASON immer noch Binär ist?
Delphi-Quellcode:
TFDJSONInterceptor.DataSetsToJSONObject(LDataSets, Result);
Delphi-Quellcode:
function TdmDALZMI.GetBauJSON(BauNr:integer): TJSONObject;
var
  LDataSets: TFDJSONDataSets;
  s:TStringList;
begin
  LDataSets := GetBau(GauNr);
  try
    Result := TJSONObject.Create;
    TFDJSONInterceptor.DataSetsToJSONObject(LDataSets, Result);

    s:=TStringList.Create;
    s.Text := result.ToString;
    s.SaveToFile('f:\JSON.txt');
    s.Free;


  finally
    LDataSets.Free;
  end;
end;

Gruß Kostas

Uwe Raabe 25. Mär 2015 15:10

AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
 
Zitat:

Zitat von Kostas (Beitrag 1294808)
ich hatte gehofft dass du als Experte mein Thread liest. :-)

:oops:

Zitat:

Zitat von Kostas (Beitrag 1294808)
Müsste das hier nicht wieder ein normales lesbares JASON erzeugen,
oder ist es normal dass das JASON immer noch Binär ist?
Delphi-Quellcode:
TFDJSONInterceptor.DataSetsToJSONObject(LDataSets, Result);

Ja, das ist normal!

Delphi-Quellcode:
TFDJSONInterceptor.DataSetsToJSONObject
läuft über
Delphi-Quellcode:
DataSetToJSONValue
und
Delphi-Quellcode:
DataSetToString
, was intern
Delphi-Quellcode:
TFDStorageFormat.sfBinary
verwendet. Insofern hast du damit also keine reelle Chance auf ein lesbares JSON.

Der gravierendste Nachteil ist dabei, daß sich das Binärformat mit jedem Delphi- bzw. FireDAC-Update ändern kann und damit die DataSets nicht mehr austauschbar sind. Bei JSON hat man wenigstens noch einen brauchbaren Ansatzpunkt.

Aber vielleicht helfen dir diese beiden Methoden weiter:

Delphi-Quellcode:
function DataSetToJSON(Source: TFDDataSet): string;
var
  stream: TStringStream;
begin
  stream := TStringStream.Create;
  try
    Source.SaveToStream(stream, TFDStorageFormat.sfJSON);
    result := stream.ToString;
  finally
    stream.Free;
  end;
end;

procedure JSONToDataSet(const Source: string; Target: TFDDataSet);
var
  stream: TStringStream;
begin
  stream := TStringStream.Create(Source);
  try
    Target.LoadFromStream(stream, TFDStorageFormat.sfJSON);
  finally
    stream.Free;
  end;
end;
Wegen der ursprünglichen Fehlermeldung muss ich nochmal forschen, wenn ich etwas Zeit habe.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:03 Uhr.
Seite 1 von 2  1 2      

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