Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
240 views
in Technique[技术] by (71.8m points)

Delphi deserialize JSON with abstract class

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.

question from:https://stackoverflow.com/questions/65893620/delphi-deserialize-json-with-abstract-class

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...