I am very much new in delphi. Presently I am facing a problem. i want to convert nested object into Json using TJson, but having memory related issue.
Here is my code.
It is just simple unit file with Person and Address class. The person class is depended on the address class.
unit uPerson;
interface
uses
REST.Json;
type
TAddress = class
private
FStreetNAme: string;
FState: string;
FPinCode: string;
published
property StreetNAme: string read FStreetNAme write FStreetNAme;
property State: string read FState write FState;
property PinCode: string read FPinCode write FPinCode;
end;
TPerson = class
private
FName: string;
FAge: Integer;
FSalary: Double;
[JSONMarshalled(True)]
FAddress: TAddress;
published
property Name: string read FName write FName;
property Age: Integer read FAge write FAge;
property Salary: Double read FSalary write FSalary;
property Address: TAddress read FAddress write FAddress;
end;
implementation
end.
Below is the main form code
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, uPerson,
REST.JSON;
type
TForm1 = class(TForm)
edtName: TLabeledEdit;
edtAge: TLabeledEdit;
edtSalary: TLabeledEdit;
edtStreet: TLabeledEdit;
edtState: TLabeledEdit;
edtPin: TLabeledEdit;
btnSave: TButton;
Memo1: TMemo;
procedure btnSaveClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Person: TPerson;
Add: TAddress;
implementation
{$R *.dfm}
procedure TForm1.btnSaveClick(Sender: TObject);
var
jsonString: string;
begin
Person := TPerson.Create;
try
Person.Name := edtName.Text;
Person.Age := Integer.Parse(edtAge.Text);
Person.Salary := double.Parse(edtSalary.Text);
Add.StreetNAme := edtStreet.Text;
Add.State := edtState.Text;
Add.PinCode := edtPin.Text;
Person.Address := Add;
jsonString := TJson.ObjectToJsonString(Person);
Memo1.Text := jsonString;
finally
Add.Free;
Person.Free;
end;
//
end;
end.
The code is compiling properly. But when try to generate the json it is giving access violation error. Here is the image - access violation error image
[Update] Basically I am getting "access violation at 0x00409fca: write of address 0x00000004".
Thank you in advance.
I don't know anything about the JSON facilities, but I do know Delphi memory management.
And this error is expected, because you forget to create the TAddress
object.
The first problem is this line:
Add.StreetNAme := edtStreet.Text;
Add
is a global variable, so it initially is set to nil
(since it is an object pointer). Consequently, you here try to write to a memory address very close to 0
, which is precisely what you see in the exception message.
You need to create a TAddress
object on the heap and assign the address of this object to the Add
variable.
Just like you do for the TPerson
object.
procedure TForm1.btnSaveClick(Sender: TObject);
var
jsonString: string;
begin
Person := TPerson.Create;
try
Add := TAddress.Create;
try
Person.Name := edtName.Text;
Person.Age := Integer.Parse(edtAge.Text);
Person.Salary := double.Parse(edtSalary.Text);
Add.StreetName := edtStreet.Text;
Add.State := edtState.Text;
Add.PinCode := edtPin.Text;
Person.Address := Add;
jsonString := TJson.ObjectToJsonString(Person);
Memo1.Text := jsonString;
finally
Add.Free;
end;
finally
Person.Free;
end;
end;
Also, it's not a good idea to use global variables here. Instead, use local variables. And there is no need for a separate TAddress
variable at all:
var
Person: TPerson;
jsonString: string;
begin
Person := TPerson.Create;
try
Person.Address := TAddress.Create;
try
Person.Name := edtName.Text;
Person.Age := Integer.Parse(edtAge.Text);
Person.Salary := double.Parse(edtSalary.Text);
Person.Address.StreetName := edtStreet.Text;
Person.Address.State := edtState.Text;
Person.Address.PinCode := edtPin.Text;
jsonString := TJson.ObjectToJsonString(Person);
Memo1.Text := jsonString;
finally
Person.Address.Free;
end;
finally
Person.Free;
end;
end;
Furthermore, you might argue that it would be better if the TPerson
constructor created a TAddress
object and put a pointer to it in its Address
field. Then the TPerson
destructor would also be responsible for freeing this object:
unit uPerson;
interface
uses
REST.Json;
type
TAddress = class
private
FStreetNAme: string;
FState: string;
FPinCode: string;
published
property StreetNAme: string read FStreetNAme write FStreetNAme;
property State: string read FState write FState;
property PinCode: string read FPinCode write FPinCode;
end;
TPerson = class
private
FName: string;
FAge: Integer;
FSalary: Double;
[JSONMarshalled(True)]
FAddress: TAddress;
public
constructor Create;
destructor Destroy; override;
published
property Name: string read FName write FName;
property Age: Integer read FAge write FAge;
property Salary: Double read FSalary write FSalary;
property Address: TAddress read FAddress write FAddress;
end;
implementation
{ TPerson }
constructor TPerson.Create;
begin
FAddress := TAddress.Create;
end;
destructor TPerson.Destroy;
begin
FAddress.Free;
inherited;
end;
end.
and
var
Person: TPerson;
jsonString: string;
begin
Person := TPerson.Create;
try
Person.Name := 'Andreas';
Person.Age := 32;
Person.Salary := 12345;
Person.Address.StreetName := 'Street';
Person.Address.State := 'State';
Person.Address.PinCode := 'pin';
jsonString := TJson.ObjectToJsonString(Person);
Memo1.Text := jsonString;
finally
Person.Free;
end;
end;
User contributions licensed under CC BY-SA 3.0