Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   TJsonSerializer und polymorphes Array? (https://www.delphipraxis.net/207263-tjsonserializer-und-polymorphes-array.html)

Whookie 8. Mär 2021 14:23

TJsonSerializer und polymorphes Array?
 
Hallo zusammen, ich habe gerade mit TJsonSerializer experimentiert und bin auf folgendes Problem gestoßen:

Delphi-Quellcode:
Type
  TMyKind = (mkA, mkB);

  [JsonSerialize(TJsonMemberSerialization.&In)]
  TBaseData = Class
    [JSonIn]
    [JsonName('Kind')]
    Kind: TMyKind;
    constructor Create; virtual;
  End;

  [JsonSerialize(TJsonMemberSerialization.&In)]
  TAData = Class(TBaseData)
    [JsonIn]
    Name: String;
    constructor Create; override;
  End;

  [JsonSerialize(TJsonMemberSerialization.&In)]
  TBData = Class(TBaseData)
    [JsonIn]
    Group: String;
    [JsonIn]
    Text: String;
    constructor Create; override;
  End;


  [JsonSerialize(TJsonMemberSerialization.&In)]
  TMyData = Class
    [JsonIn]
    [JsonObjectHandling(TJsonObjectHandling.Reuse)]
    Data: TArray<TBaseData>;

    [JsonIn]
    MainData: TBaseData;

    constructor Create; virtual;
    Destructor Destroy; override;
  End;


...

{ TMyData }

constructor TMyData.Create;
begin
  inherited;
  SetLength(Data, 2);
  Data[0] := TAData.Create;
  Data[1] := TBData.Create;
  MainData := TBData.Create;
end;
Ich habe also ein Data[] das eine TAData und eine TBData instanz enthält. Beim serialisieren funktioniert das wunderbar:

Delphi-Quellcode:
  fMyData := TMyData.Create;

  js := TJsonSerializer.Create;
  js.Formatting := TJsonFormatting.Indented;
  s := js.Serialize(fMyData);
  ...
  Memo.Text := s;
Code:
{
    "Data": [
        {
            "Name": "A",
            "Kind": 1
        },
        {
            "Group": "B",
            "Text": "C",
            "Kind": 0
        }
    ],
    "MainData": {
        "Group": "D",
        "Text": "E",
        "Kind": 1
    }
}
Beim Versuch dieses JSON mit Populate wieder einzulesen wird dann aber das Array neu erzeugt (alle Elemente vom Typ TBaseData).

Delphi-Quellcode:
  LMyData := TMyData.Create;
  js := TJsonSerializer.Create;
  js.Populate<TMyData>(Memo.Text, LMyData);
  // LMyData.Data[0] = TBaseData
  // LMyData.Data[1] = TBaseData
  // LMyData.MainData = TBData
  ...
  Memo.Text := js.Serialize(LMyData)
Das ergibt nach erneuter Serialisierung:
Code:
{
    "Data": [
        {
            "Kind": 1
        },
        {
            "Kind": 0
        }
    ],
    "MainData": {
        "Group": "D",
        "Text": "E",
        "Kind": 1
    }
}
Ich hatte allerdings gehofft, dass durch Angabe von
Delphi-Quellcode:
JsonObjectHandling(TJsonObjectHandling.Reuse)
die übergebenen Instanzen erhalten bleiben.

Frage 1: Gibt es eine Möglichkeit, die korrekten Typen für die Array-Elemente zu erhalten?
Frage 2: Kann man die Reihenfolge in der js.Serialize den Ausgabestring erzeugt umdrehen (geerbte Properies zuerst -> "Kind" vor "Name")?


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