I want to serialize and deserialize an object with the built-in functions TJson.JsonToObject<T>
and TJson.ObjectToJsonObject
. The object contains some nested objects and one of these is of an abstract type. Is there any chance, to tell the deserializer, which concrete object to create? Can I maybe use a custom JSONInterceptor for this nested object?
The classes are defined as following:
type
TAngPos = class (TObject)
strict private
var
FPrimkey: Integer;
FAng_ID: Integer;
FPosNr: Integer;
FArt_ID: Integer;
FPositionstyp: TPositionstyp; // <--- abstract
end;
type
TPositionstyp = class abstract (TObject)
strict protected
var
FArtikel: TArtikel;
end;
type
TPositionstypArtikel = class (TPositionstyp);
type
TPositionstypAngPosKonf = class (TPositionstyp)
strict private
var
FGrundeinheit: TAngPos;
FEinbaukomponenten: TObjectList<TAngPos>;
end;
type
TArtikel = class (TObject)
strict private
var
FPrimkey: Integer;
FStatus: Integer;
FTyp: Integer;
FBeschreibung: string;
FHerstellerNr: string;
end;
The corresponding JSON looks like this:
for TPositionstypArtikel:
{
"primkey": 23930,
"ang_ID": 2400,
"posNr": 40,
"art_ID": 46210,
"positionstyp": { // PositionstypArtikel
"artikel": {
"primkey": 46210,
"status": 1,
"typ": 2,
"beschreibung": "MyDescription",
"herstellerNr": "MyVendorNr"
}
}
}
and for TPositionstypAngPosKonf
{
"primkey": 2,
"ang_ID": 1,
"posNr": 10,
"art_ID": 44041,
"positionstyp": { // TPositionstypAngPosKonf
"grundeinheit": { // <-- TAngPos
"primkey": 33067,
"ang_ID": 0,
"posNr": 20,
"art_ID": 44092,
"positionstyp": {
"artikel": {
"primkey": 44092,
"status": 2,
"typ": 4,
"beschreibung": "MyDescriptionGrundeinheit",
"herstellerNr": "MyVendorNrGrundeinheit"
}
}
},
"einbaukomponenten": { // <-- TObjectList<TAngPos>
"ownsObjects": true,
"listHelper": [
{
"primkey": 33068,
"ang_ID": 0,
"posNr": 30,
"art_ID": 44399,
"positionstyp": {
"artikel": {
"primkey": 44399,
"status": 2,
"typ": 4,
"beschreibung": "MyDescriptionEinbaukomponente1",
"herstellerNr": "MyVendorNrEinbaukomponente1"
}
}
},
{
"primkey": 33069,
"ang_ID": 0,
"posNr": 40,
"art_ID": 44398,
"positionstyp": {
"artikel": {
"primkey": 44398,
"status": 2,
"typ": 4,
"beschreibung": "MyDescriptionEinbaukomponente2",
"herstellerNr": "MyVendorNrEinbaukomponente2"
}
}
}
]
},
"artikel": {
"primkey": 44041,
"status": 1,
"typ": 3,
"beschreibung": "MyDescriptionKonfKopf",
"herstellerNr": ""
}
}
After deserialization of the object, I can check, if the nested object is of a specific type with the is
-operator, but unfortunately it's neither TPositionstypArtikel
nor TPositionstypAngPosKonf
.
Thanks for the comments. I ended up in changing the structure of the class. It doesn't contain the abstract type anymore, but rather a separate variable of type TPositionstypAngPosKonf
, which is either nil
or not. The TArtikel
from the TPositionstyp
now inhabits directly in the TAngPos
and the two classes TPositionstyp
and TPositionstypArtikel
don't exist anymore. So it basically looks like this
type
TAngPos = class (TObject)
strict private
var
FPrimkey: Integer;
FAng_ID: Integer;
FPosNr: Integer;
FArt_ID: Integer;
FArtikel: TArtikel;
FPositionstypAngPosKonf: TPositionstypAngPosKonf; // may be nil
end;
type
TPositionstypAngPosKonf = class (TObject)
strict private
var
FGrundeinheit: TAngPos;
FEinbaukomponenten: TObjectList<TAngPos>;
end;
type
TArtikel = class (TObject)
strict private
var
FPrimkey: Integer;
FStatus: Integer;
FTyp: Integer;
FBeschreibung: string;
FHerstellerNr: string;
end;