FNC Hidden Gems: JSON persistence

  

Intro
FNC has evolved over time. Each update brings new features, some of them are visible at designtime/runtime. Some of time are happening behind the screens. Some updates are bringing a lot of fixes to make FNC more stable across the multiple frameworks and platforms FNC supports. JSON persistence is one of those hidden gems that is available in TMS FNC Core. Today's blog brings a step by step tutorial on how to implement JSON persistence in your application, and how to import objects from JSON.
Getting Started
JSON formatted data can come from a REST service, a database, a local file, plain text … . It's an easy to read/learn/use and consume format and in FNC we have added support for mapping objects to JSON and vice versa. The code below is a sample of JSON that we will map on an object in Delphi. We'll focus on having an object that can access the properties shown in this JSON:
{
“$type”:”TPerson”,
“address”:{
“$type”:”TPersonAddress”,
“addressLocality”:”Colorado Springs”,
“addressRegion”:”CO”,
“postalCode”:”80840″,
“streetAddress”:”100 Main Street”
},
“colleague”:[
“http://www.example.com/JohnColleague.html”,
“http://www.example.com/JameColleague.html”
],
“email”:”info@example.com”,
“jobTitle”:”Research Assistant”,
“name”:”Jane Doe”,
“birthDate”:”1979-10-12″,
“gender”:”female”,
“nationality”:”Albanian”,
“telephone”:”(123) 456-6789″,
“url”:”http://www.example.com”,
}

For accessing this data we need to define our classes first:

type
TPersonAddress = class(TPersistent)
private
FPostalCode: string;
FAddressLocality: string;
FAddressRegion: string;
FStreetAddress: string;
published
property AddressLocality: string read FAddressLocality write FAddressLocality;
property AddressRegion: string read FAddressRegion write FAddressRegion;
property PostalCode: string read FPostalCode write FPostalCode;
property StreetAddress: string read FStreetAddress write FStreetAddress;
end;

TPerson = class(TPersistent)
private
FAddress: TPersonAddress;
FColleague: TStringList;
FBirthDate: string;
FName: string;
FEmail: string;
FTelephone: string;
FGender: string;
FNationality: string;
FJobTitle: string;
FURL: string;
public
constructor Create;
destructor Destroy; override;
published
property Address: TPersonAddress read FAddress;
property Colleague: TStringList read FColleague;
property Email: string read FEmail write FEmail;
property JobTitle: string read FJobTitle write FJobTitle;
property Name: string read FName write FName;
property BirthDate: string read FBirthDate write FBirthDate;
property Gender: string read FGender write FGender;
property Nationality: string read FNationality write FNationality;
property Telephone: string read FTelephone write FTelephone;
property URL: string read FURL write FURL;
end;

And the JSON data (please note that linebreaks and whitespaces are currently not supported, but this is being worked on!.

const
jsonSample =
'{' +
'”$type”: “TPerson”,' +
'”address”:{' +
'”$type”: “TPersonAddress”,' +
'”addressLocality”:”Colorado Springs”,' +
'”addressRegion”:”CO”,' +
'”postalCode”:”80840″,' +
'”streetAddress”:”100 Main Street”' +
'},' +
'”colleague”:[' +
'”http://www.example.com/JohnColleague.html”,' +
'”http://www.example.com/JameColleague.html”' +
'],' +
'”email”:”info@example.com”,' +
'”jobTitle”:”Research Assistant”,' +
'”name”:”Jane Doe”,' +
'”birthDate”:”1979-10-12″,' +
'”gender”:”female”,' +
'”nationality”:”Albanian”,' +
'”telephone”:”(123) 456-6789″,' +
'”url”:”http://www.example.com”' +
'}';

There are multiple ways to map the JSON onto the TPerson object.

1. Use the TTMSFNCPersistence class
Add the unit *TMSFNCPersistence to the uses list (* = FMX., LCL, VCL., WEBLib.), and use the following code:

var
p: TPerson;
s: TStringStream;
begin
p := TPerson.Create;
s := TStringStream.Create(jsonSample);
try
TTMSFNCPersistence.LoadSettingsFromStream(p, s);
finally
s.Free;
p.Free;
end;
end;

2. Use the object class helper in *TMSFNCTypes unit
An alternative is to use the class helper that maps JSON to the object.

var
p: TPerson;
begin
p := TPerson.Create;
try
p.JSON := jsonSample;
finally
p.Free;
end;
end;

Writing to JSON is as easy as reading. Simply use SaveSettingsToFile or SaveSettingsToStream or use the JSON object class helper to get the JSON from the object.

p: TPerson;
begin
p := TPerson.Create;
try
p.JSON := jsonSample;
p.Name := 'tmssoftware.com';
TTMSFNCUtils.Log(p.JSON);
//or
TTMSFNCPersistence.SaveSettingsToFile(p, 'TPerson.json');
finally
p.Free;
end;
end;

Note that this code will also work on other frameworks such as VCL, LCL and WEB. Below is the full code sample that demonstrates JSON persistence. Please let us know if you have suggestions on what to add to TMS FNC Core in the future!

unit Unit1;

interface

uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.Controls.Presentation, FMX.StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.fmx}

uses
FMX.TMSFNCTypes, FMX.TMSFNCPersistence;

const
jsonSample =
'{' +
'”$type”: “TPerson”,' +
'”address”:{' +
'”$type”: “TPersonAddress”,' +
'”addressLocality”:”Colorado Springs”,' +
'”addressRegion”:”CO”,' +
'”postalCode”:”80840″,' +
'”streetAddress”:”100 Main Street”' +
'},' +
'”colleague”:[' +
'”http://www.example.com/JohnColleague.html”,' +
'”http://www.example.com/JameColleague.html”' +
'],' +
'”email”:”info@example.com”,' +
'”jobTitle”:”Research Assistant”,' +
'”name”:”Jane Doe”,' +
'”birthDate”:”1979-10-12″,' +
'”gender”:”female”,' +
'”nationality”:”Albanian”,' +
'”telephone”:”(123) 456-6789″,' +
'”url”:”http://www.example.com”' +
'}';

type
TPersonAddress = class(TPersistent)
private
FPostalCode: string;
FAddressLocality: string;
FAddressRegion: string;
FStreetAddress: string;
published
property AddressLocality: string read FAddressLocality write FAddressLocality;
property AddressRegion: string read FAddressRegion write FAddressRegion;
property PostalCode: string read FPostalCode write FPostalCode;
property StreetAddress: string read FStreetAddress write FStreetAddress;
end;

TPerson = class(TPersistent)
private
FAddress: TPersonAddress;
FColleague: TStringList;
FBirthDate: string;
FName: string;
FEmail: string;
FTelephone: string;
FGender: string;
FNationality: string;
FJobTitle: string;
FURL: string;
public
constructor Create;
destructor Destroy; override;
published
property Address: TPersonAddress read FAddress;
property Colleague: TStringList read FColleague;
property Email: string read FEmail write FEmail;
property JobTitle: string read FJobTitle write FJobTitle;
property Name: string read FName write FName;
property BirthDate: string read FBirthDate write FBirthDate;
property Gender: string read FGender write FGender;
property Nationality: string read FNationality write FNationality;
property Telephone: string read FTelephone write FTelephone;
property URL: string read FURL write FURL;
end;

{ TPerson }

constructor TPerson.Create;
begin
FAddress := TPersonAddress.Create;
FColleague := TStringList.Create;
end;

destructor TPerson.Destroy;
begin
FreeAndNil(FAddress);
FreeAndNil(FColleague);
inherited;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
p: TPerson;
begin
p := TPerson.Create;
try
p.JSON := jsonSample;
finally
p.Free;
end;
end;

end.

Comments are closed.