Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi JSON Marchalling funktioniert nicht mit Generics (https://www.delphipraxis.net/201049-json-marchalling-funktioniert-nicht-mit-generics.html)

OlliWW 18. Jun 2019 21:01

JSON Marchalling funktioniert nicht mit Generics
 
Hallo,

Da die Rest Bibliothek unter Delphi 10.3 ja etwas kaputt ist, versuche ich per JSON Marchal / Unmarchal Objekte in JSON umzuwandeln und umgekehrt.
Das funktioniert mit festgelegten Datentypen auch sehr gut.
Nun wollte ich meine Methoden aufgrund von Wiederverwendbarkeit etwas generischer schreiben. Aber hier scheint Delphi ein Problem zu haben.

Mein Objekt sieht so aus:
Es gibt eine Klasse, die hat wiederrum ein generisches Array als Property. So kann ich listen von Objekten per Json hin und her übertragen.

Wenn ich dies allerdings nun mit Generics schreibe, hat das Unmarchalling ein Problem, es kann die Instanz nicht erstellen.

Hier mal das Code, der das Ganze verdeutlicht:

Delphi-Quellcode:
tyoe

TwwObjekt = class
  public
    wert1: String;
    wert2: String;
end;

TwwRestObjektListe<T> = class(TObject)
  strict private
    FObjekte: TArray<T>;
  public
    property lstObjekte: TArray<T> read FObjekte write FObjekte;
end;

Diesen Teil nutze ich um die Objekte umzuwandeln:
Delphi-Quellcode:
var
  lst: TwwRestObjektListe<TwwObjekt>;
  aObjs: TArray<TwwObjekt>;
  obj: TwwObjekt;
  Mar: TJSONMarshal;
  jsObjekt: TJSONObject;
  jsUnMarshal: TJSONUnMarshal;
  jsValue: TJSONValue;
begin
  lst := TwwRestObjektListe<TwwObjekt>.Create;
  SetLength(aObjs, 1);
  obj := TwwObjekt.Create;
  obj.wert1 := '1234';
  obj.wert2 := '1';
  aObjs[0] := obj;
  lst.lstObjekte := aObjs;

  Mar := TJSONMarshal.Create(TJSONConverter.Create);
  try
    jsObjekt := Mar.Marshal(lst) as TJSONObject;
    edtLines.Lines.Add(jsObjekt.ToString);
  finally
    FreeAndNil(Mar);
  end;


  jsUnMarshal := TJSONUnMarshal.Create;
  try
    jsValue := TJSONObject.ParseJSONValue(jsObjekt.ToString);
    try
      /// =>>>>> HIER SCHLÄGT ES FEHL
      lst := jsUnMarshal.Unmarshal(jsValue) as TwwRestObjektListe<TwwObjekt>;
    finally
      FreeAndNil(jsValue);
    end;
  finally
    FreeAndNil(jsUnMarshal);
  end;

end;
Ein JSON Objekt sieht dann so aus:
Code:
{"type":"Unit2.TwwRestObjektListe<Unit2.TwwObjekt>","id":1,"fields":{"FObjekte":[{"type":"Unit2.TwwObjekt","id":2,"fields":{"wert1":"1234","wert2":"1"}}]}}
Dies ist laut Validator ein gültiges JSON Objekt.

Fehlermeldung:
Typ Unit2.TwwRestsObjektListe<Unit2.TwwObjekt> kann nicht instantiiert werden


Vielleicht habe ich ja auch nur einen Denkfehler.

Stevie 18. Jun 2019 21:39

AW: JSON Marchalling funktioniert nicht mit Generics
 
Der Code, um aus dem String den Typ zu finden, nutzt dafür TRttiContext.FindType.
Die Typen, die in dieser Methode durchsucht werden, sind die sogenannten public types.

Typen, die nur in Methodenimplementierungen zu finden sind, wie bei dem Codeschnipsel, den du gepostet hast, sind dort nicht enthalten.

Damit der Typ in den public Types landet, kannst du einfach folgenden Code in den interface Teil deiner Unit2 hinzufügen:

Delphi-Quellcode:
type
  TDummy = class
    x: TwwRestObjektListe<TwwObjekt>;
  end;
Dann findet das JSON Marshal Dings den Typen.


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