BlogAll Blog Posts | Next Post | Previous Post
JSON persistence in VCL: genericsBookmarks:
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: https://www.tmssoftware.com/site/blog.asp?post=971
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)
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)
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
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: https://github.com/SwiftExpat/FNC_JSON_Samples/tree/main/Garage_Car_Collection
Author: Neil Laskowski
All Blog Posts | Next Post | Previous Post