Delphi 使用抽象 class 反序列化 JSON

Delphi deserialize JSON with abstract class

我想使用内置函数 TJson.JsonToObject<T>TJson.ObjectToJsonObject 序列化和反序列化一个对象。该对象包含一些嵌套对象,其中之一是抽象类型。有没有机会告诉反序列化器要创建哪个具体对象?我可以为这个嵌套对象使用自定义 JSON拦截器吗?

类定义如下:

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;

对应的JSON是这样的:

对于 TPositionstypArtikel:

{
  "primkey": 23930,
  "ang_ID": 2400,
  "posNr": 40,
  "art_ID": 46210,
  "positionstyp": { // PositionstypArtikel
    "artikel": {
      "primkey": 46210,
      "status": 1,
      "typ": 2,
      "beschreibung": "MyDescription",
      "herstellerNr": "MyVendorNr"
    }
  }
}

对于 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": ""
      }
    }

对象反序列化后,我可以使用 is 运算符检查嵌套对象是否属于特定类型,但不幸的是它既不是 TPositionstypArtikel 也不是 TPositionstypAngPosKonf

感谢您的评论。我最终改变了 class 的结构。它不再包含抽象类型,而是一个单独的 TPositionstypAngPosKonf 类型的变量,它可以是 nil 也可以不是。来自 TPositionstypTArtikel 现在直接居住在 TAngPos 中,而两个 classes TPositionstypTPositionstypArtikel 不再存在。所以它基本上看起来像这样

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;