![]() |
AW: ObjectList serialisieren JSON
Zitat:
Zitat:
Das wäre dann vielleicht mal was für eine Erweiterung der REST.Json.Helpers Unit. :) |
AW: ObjectList serialisieren JSON
Ich habe das für mich jetzt so gelöst, dass ich mir eine Basisklasse TJSONSerializable erstellt habe. Diese geht per RTTI ihre eigenen Properties durch und schaut, ob diese ein Attribut JSONFieldName aufweisen, in welchem der Keyname des JSON-Pairs angegeben ist. Zum Serialisieren wird ein TJSONObject erzeugt und die erwähnten JSON-Pairs gemäß der Readable-Properties hinzugefügt. Zum Deserialisieren geht das Ganze dann für die Writable-Properties andersherum. Eine spezialisierte generische TObjectList gibt es auch, die erstellt dann ein JSONArray mit Elementen der serialisierten TJSONSerializable-Instanzen. Leider habe ich diese Klasse für die Firma geschrieben und darf sie daher nicht einfach veröffentlichen, aber in dem Zusammenhang gibt es hier einen Thread von mir:
![]() Da das IMHO unkritisch ist, kann ich aber zumindest Ausschnitte des Interface-Abschnitts zeigen:
Delphi-Quellcode:
Benutzen lässt sich dann beispielsweise so:
uses System.SysUtils, System.JSON, System.Generics.Collections, System.Rtti;
type (* Attribut, mit dem gesteuert wird, wie das Feld im JSON-Objekt heißt/heißen soll *) JSONFieldNameAttribute = class(TCustomAttribute) private FFieldname: string; public constructor Create(const AFieldName: string); property Fieldname: string read FFieldname; end; (* Attribut, mit dem angegeben wird, dass der Standardwert des entsprechenden Property-Datentyps als NULL ausgegeben werden soll. Betrifft nur die Wandlung in JSON, andersherum nicht, da Delphi keine echten Nullables kennt. *) JSONNullIfDefaultAttribute = class(TCustomAttribute); // Forward-Deklarationen für die Klassenfunktion FromJSON TJSONSerializable = class; TJSONSerializableClass = class of TJSONSerializable; (* Die Parent-Klasse für JSON-Serialisierung. Betrachtet werden alle Properties, die das JSONFieldName-Attribut (s.o.) haben. Geparst werden einfache Datentypen, Arrays, Objekte (falls von TJSONSerializable abgeleitet) und Listen, sofern diese generisch sind. Heißt: TList<string> wird abgearbeitet, TStringList hingegen nicht. Wir leiten von TInterfacedObject ab, damit wir in Ableitungen ggf. noch Interfaces anflanschen können und damit automatische Referenzzählung haben. *) TJSONSerializable = class(TInterfacedObject) public constructor Create; virtual; function ToJSON: TJSONObject; virtual; // Parameter: // Obj = das zu parsende JSON-Objekt // AClass = die zu erzeugende konkrete Klasse (Ableitung von TJSONSerializable) // Um das erzeugte Objekt dann auch vollständig nutzen zu können, muss // es noch in den konkreten Typ gecastet werden: // MyObj := TMyObj.FromJSON(JsonObjekt, TMyObj) as TMyObj; class function FromJSON(const Obj: TJSONObject; const AClass: TJSONSerializableClass): TJSONSerializable; static; end; TJSONSerializableObjectList<T: TJSONSerializable> = class(TObjectList<T>) public function ToJSON: TJSONArray; virtual; class function FromJSON(const Obj: TJSONArray): TJSONSerializableObjectList<T>; static; end;
Delphi-Quellcode:
type
TUserDB = class(TJSONSerializable) private FName: String; FWinAuth: Boolean; FIsMySQL: Boolean; FPort: Word; FDatabase: String; FPassword: String; FUser: String; FServer: String; public [JSONFieldName('Name')] property Name: String read FName write FName; [JSONFieldName('Server')] property Server: String read FServer write FServer; [JSONFieldName('IsMySql')] property IsMySql: Boolean read FIsMySQL write FIsMySQL; [JSONFieldName('User')] property User: String read FUser write FUser; [JSONFieldName('Database')] property Database: String read FDatabase write FDatabase; [JSONFieldName('Password')] property Password: String read FPassword write FPassword; [JSONFieldName('Port')] [JSONNullIfDefault] property Port: Word read FPort write FPort; [JSONFieldName('WinAuth')] property WinAuth: Boolean read FWinAuth write FWinAuth; end; ... UserDB := TUserDB.Create; ... {TJSONObject}lObj := UserDB.ToJSON; |
AW: ObjectList serialisieren JSON
Zitat:
Zitat:
![]() Bezogen auf dein Code-Beispiel und erweitert um die direkten Verarbeitung der Listen könnte das nun so aussehen:
Delphi-Quellcode:
type
TPerson = class private FName: String; public property Name: String read FName write FName; end; JsonObjectListPersonAttribute = class(JsonObjectListAttribute<TPerson>); type [JsonObjectListPerson] TPersonListe = class(TObjectList<TPerson>); type { Wrapper } TPersonJSON = class private [JSONOwned(False)] FPersonListe: TPersonListe; public constructor Create; destructor Destroy; override; property PersonListe: TPersonListe read FPersonListe write FPersonListe; end; ... const cNamen: TArray<String> = ['Name1', 'Name2', 'Name3']; cPersonListe = '[{"name":"Name1"},{"name":"Name2"},{"name":"Name3"}]'; cPersonJSON = '{"personListe":[{"name":"Name1"},{"name":"Name2"},{"name":"Name3"}]}'; function CheckListe(AListe: TPersonListe): Boolean; var I: Integer; begin Result := (AListe.Count = Length(cNamen)); if Result then begin for I := 0 to AListe.Count - 1 do if AListe[I].Name <> cNamen[I] then Exit(False); end; end; var lPersonJSON: TPersonJSON; lPerson: TPerson; lJSONString: String; lPersonListe: TPersonListe; begin { mit Wrapper } lPersonJSON := TPersonJSON.Create; try for var lName in cNamen do begin lPerson := TPerson.Create; lPerson.Name := lName; lPersonJSON.PersonListe.Add(lPerson); end; lJSONString := TConvert.ToJSONString(lPersonJSON); Assert(lJSONString = cPersonJSON); finally lPersonJSON.Free; end; lPersonJSON := TConvert.FromJSON<TPersonJSON>(cPersonJSON); try Assert(CheckListe(lPersonJSON.PersonListe)); finally lPersonJSON.Free; end; { Liste direkt } lPersonListe := TPersonListe.Create; try for var lName in cNamen do begin lPerson := TPerson.Create; lPerson.Name := lName; lPersonListe.Add(lPerson); end; lJSONString := TConvert.ToJSONString(lPersonListe); Assert(lJSONString = cPersonListe); finally lPersonListe.Free; end; lPersonListe := TPersonListe.Create; try lPersonListe.AddRange(TConvert.FromJSONArray<TPerson>(cPersonListe)); Assert(CheckListe(lPersonListe)); finally lPersonListe.Free; end; end; |
AW: ObjectList serialisieren JSON
Bei
Code:
bekomme ich einen Fehler mit der Meldung 'Assertion fehlgeschlagen....' (Delphi 11)
lJSONString := TConvert.ToJSONString(lPersonJSON);
|
AW: ObjectList serialisieren JSON
Zitat:
Hmm, kommt hier nicht - auch Delphi 11. Kannst du das komplette Projekt posten? |
AW: ObjectList serialisieren JSON
Liste der Anhänge anzeigen (Anzahl: 1)
Klar!
|
AW: ObjectList serialisieren JSON
Zwischen der Deklaration von JsonObjectListPersonAttribute und dessen Verwendung muss mindestens ein type stehen.
Steht auch so in der Readme: Zitat:
|
AW: ObjectList serialisieren JSON
Vielen Dank! Das hatte ich überlesen und habe wieder was dazu gelernt. Das das zweite Type notwendig ist hätte ich auch nicht erwartet.
|
AW: ObjectList serialisieren JSON
Darf es auch etwas anderes sein? Ich bringe mal das Open Source Framework mORMot ins Spiel. mORMot ist von D7 bis Delphi 11 Alexandria verfügbar. Eine ausführliche Hilfe findest du hier:
![]() ![]() ![]() Mit mORMot kannst du die Published Eigenschaften eines Objekts/Objektliste ohne einen eigenen JSON Serializer schreiben und lesen. Das geht auch bei verschachtelten Objekt-Strukturen. Mit ObjArrayToJson() wird z.B. ein Array of TPerson gespeichert. mORMot verarbeitet fast alles.
Delphi-Quellcode:
Bis bald...
type
TPerson = class(TObject) private FName: String; published property Name: String read FName write FName; end; FPersonListe: TObjectList; // In eine Datei speichern ObjectToJsonFile(FPersonListe, 'test.json', [woObjectListWontStoreClassName]); // Aus einer Datei laden JsonFileToObject('test.json', FPersonListe, TPerson); initialization Rtti.RegisterClasses([TPerson]); Thomas |
AW: ObjectList serialisieren JSON
@mytbo mORMot ist Top habe deine Hilfe diesbezüglich auch nicht vergessen. :thumb:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:32 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz