Einzelnen Beitrag anzeigen

Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.544 Beiträge
 
Delphi 11 Alexandria
 
#12

AW: ObjectList serialisieren JSON

  Alt 10. Nov 2021, 14:45
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: https://www.delphipraxis.net/209157-...-erkennen.html

Da das IMHO unkritisch ist, kann ich aber zumindest Ausschnitte des Interface-Abschnitts zeigen:
Delphi-Quellcode:
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;
Benutzen lässt sich dann beispielsweise so:
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;
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat