All Blog Posts  |  Next Post  |  Previous Post

JSON persistence in VCL: generics


Monday, January 16, 2023

This sample demonstrates how to use TMS FNC Core JSON to deal with generics and restoring using the interfaces that are recognized by FNC JSON. The link to the source code and sample can be found at the end of this article. The sample is going to refer to a dictionary of different car types. Currently the garage holds 2 types of cars, TGasolineCar and TElectricCar both are class(TCar) and the collection is defined as TObjectDictionary<string, TCar> to allow all cars to be added to the garage.

The sample is for you to set debug break points to be able to trace the execution, notes are included in the code where I felt clarification was needed.

Reference to the initial JSON persistence blog post can be found here:

The article above lacks abstract and derived classes, so in this code I have implemented abstract and derived to allow you to set breakpoints and examine where the calls to CreateObject.


Root Object - TGarage Implements ITMSFNCBasePersistenceIO

  TGarage = class(TInterfacedPersistent, ITMSFNCBasePersistenceIO)
  strict private
    FCarList: TCarList;
    FName: string;
    procedure LoadCars;
    function CreateObject(const AClassName: string; const ABaseClass: TClass): TObject;
    constructor Create(ALoadCars: boolean = true);
    destructor Destroy; override;
    class procedure RegisterJsonClasses;
    property Name: string read FName write FName;
    property CarList: TCarList read FCarList;

Your root object needs to implement ITMSFNCBasePersistenceIO, this will allow your object to create the correct class type on restore using the function, CreateObject. The list that holds the cars is covered next.

Generic List - TCarList Implements ITMSFNCBaseListIO

  TCarList = class(TObjectDictionary<string, TCar>, ITMSFNCBaseListIO)
    FOwnerInterface: IInterface;
    function GetItemClass: TClass;
    function _AddRef: integer; stdcall;
    function _Release: integer; stdcall;
    function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;

Implementing the ITMSFNCBaseListIO allows the framework to query the base type of the item class in the list, this will be passed back to CreateObject in the Root Object class.


The form create event is used to create a TGarage and load some cars, then display it in an FNCTree so that you can compare the values.

Export Object to JSON

FNC has a object help to expose a JSON property, so here the JSON is captured to a string variable

  FJson := FGarage.JSON;

Import Object from JSON

Since this object requires types, there is a little more code here. Capture and RESTORE the IO and root refrences when you Load your object. These are class var for the TTMSFNCPersistence class so you are assigning them and must restore, just use a try finally block.

procedure TfrmJsonGarageV.btnImportClick(Sender: TObject);
  g: TGarage; // a new object to restore to
  FOPIORef, FOPRoot: TObject; // capture the references
  // capture the refs to be able to restore after finished
  FOPIORef := TTMSFNCPersistence.IOReference; // class var needs to be restored after use
  FOPRoot := TTMSFNCPersistence.RootObject; // class var needs to be restored after use
    // create the new object that will be the destination for the data
    g := TGarage.Create(false); // false creates it without cars
    // IO Reference allows the framework to ask your object to create the destination classes
    TTMSFNCPersistence.IOReference := g; // set the IO Reference
    TTMSFNCPersistence.RootObject := g; // set the Root Object
    // Load the new object with a copy of the original object
    TTMSFNCObjectPersistence.LoadObjectFromString(g, FJson);
    TTMSFNCPersistence.IOReference := FOPIORef; // restore
    TTMSFNCPersistence.RootObject := FOPRoot; // restore
  tvImport.ViewJSONFromText(g.JSON); // load the tree to view the JSON


The full sample can be found here:

Author: Neil Laskowski

Masiha Zemarai


All Blog Posts  |  Next Post  |  Previous Post