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:
Hat jemand eine Idee wo denn das Problem sein könnte oder gibt es eine einfachere Art eine
//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; 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 |
AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
Zitat:
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 |
AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
Er meint nicht den Query-String, sondern das aus der Query resultierende TDataSet.
|
AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
Zitat:
|
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 |
AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
Zitat:
|
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 |
AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
Zitat:
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. |
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 |
AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
Zitat:
Zitat:
Delphi-Quellcode:
läuft über
TFDJSONInterceptor.DataSetsToJSONObject
Delphi-Quellcode:
und
DataSetToJSONValue
Delphi-Quellcode:
, was intern
DataSetToString
Delphi-Quellcode:
verwendet. Insofern hast du damit also keine reelle Chance auf ein lesbares JSON.
TFDStorageFormat.sfBinary
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:
Wegen der ursprünglichen Fehlermeldung muss ich nochmal forschen, wenn ich etwas Zeit habe.
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; |
AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
Ein herzliches Dankeschön Uwe,
werde ich gleich mal umsetzen. Sicherlich ist es nur eine Kleinigkeit das ursprüngliche Problem, ich übersehe sicherlich etwas. Danke nochmals, Gruß Kostas |
AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
Hallo zusammen,
so funktioniert es jetzt einwandfrei. Dankeschön Uwe.
Delphi-Quellcode:
-------------------------------SERVER---------------------
function TdmDALZMI.GetBauJSONStr(BauNr:integer): String; var stream: TStringStream; begin stream := TStringStream.Create; try qrGetBau.Active := False; qrGetBau.Params[0].Value := BauNr; qrGetBau.Active := True; qrGetBau.SaveToStream(stream, TFDStorageFormat.sfJSON); stream.Seek(0, soFromBeginning); qrGetBau.Active := False; result := stream.DataString; finally stream.Free; end; end; -------------------------------CLIENT--------------------- procedure TdmZMI.GetBauJSONStr(BauNr:integer); var LDataSetList: TFDJSONDataSets; LJSONStr: String; LZMIClient: TdmServerMethodsZMIClient; begin LZMIClient := TdmServerMethodsZMIClient.Create(CMClientModule.CMCSQLConnection.DBXConnection); try LJSONStr := LZMIClient.ZMI_GetBauJSONStr(BauNr); JSONToDataSet(LJSONStr, mtBau); finally LZMIClient.Free; end; mtBau.Open; end; procedure TdmZMI.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; Gruß Kostas |
AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
Noch eine Kleinigkeit,
der Server liefert das Result als String. Ist es hier sinnvoll ein TStream auszugeben da das Select schon durchaus eine größere Datenmenge liefern könnte? Gruß Kostas |
AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
Bei Streams mußt du etwas aufpassen, da der DataSnap-Stream gern Mal etwas anders arbeitet (Size = -1, ab einer gewissen Größe).
Meine alten Threads dazu sollten sich bestimmt finden lassen. Aber wenn du sowieso eh "nur" ein DataSet übertragen willst, dann übertrage Dieses direkt, ohne es erst umzuwandeln. :stupid:
Delphi-Quellcode:
function TdmDALZMI.GetBau(BauNr: Integer): TDataSet;
|
AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
Zitat:
Zitat:
|
AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
Nee, wieso?
Man sagt dem DataSnap, daß es seine Datei als JSON und nicht binär übertragen soll. DataSnap benutzt DBX für die Connection und DBX kann Beides. Beiß jetzt nur nicht mehr, wie das genau war ... irgendwo gab es auch ein Transport-Event, wo man den rausgehenden und reinkommenden Traffic des Servers loggen konnte. Das hatten wir damals mal benutzt, als es mit DataSnap anfing und dort sind die DataSets schön als JSON durchgerauscht. |
AW: DataSnap ein TFDJSONDataSets als TJSONObject übertragen
Hallo Zusammen,
ich habe umgestellt auf DataSet übertragen das funktioniert einwandfrei. Zuvor wird wegen Log das DataSet als Jason exportiert und Serverseitig gespeichert. Somit alles im grünen Bereich. Herzlichen Dank schon mal an alle. Jetzt hätte ich noch eine architektonische Frage zu DataSnap. Ich werde ein neun Thread dafür erstellen. Gruß Kostas |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:25 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