You are not logged in.
Pages: 1
I tried save instance of object with ObjectToJSON. And it's really ok. But a want to load my file, i get message "not valid". In debug i found, when parser read nested TObjectList = TDevice, it can not detect its.
Try this code.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, SynCommons, mORMot, Contnrs, StdCtrls;
type
TSpeed = (s9600,s38400);
TLine = class;
TConfig = class;
TDevice = class(TPersistent)
strict private
fParentLine : TLine;
fName : string;
fSpeed : TSpeed;
fAdress : Integer;
public
constructor Create(ALine:TLine;AName:string;Adress:Integer);
property ParentLine : TLine read fParentLine write fParentLine;
published
property Name : string read fName write fName;
property Speed : TSpeed read fSpeed write fSpeed;
property Adress : Integer read fAdress write fAdress;
end;
TLine = class(TPersistent)
strict private
fParentConfig : TConfig;
fListDevices : TObjectList;
fName : string;
fComPort : string;
fIniFile : string;
public
constructor Create(AConfig:TConfig;ANameLine,AComPort:string);
destructor Destroy; override;
function AddDevice(AName:string):TDevice;
property ParentConfig : TConfig read fParentConfig write fParentConfig;
published
property NameLine : string read fName write fName;
property ComPort : string read fComPort write fComPort;
property IniFile : string read fIniFile write fIniFile;
property ListDevices : TObjectList read fListDevices write fListDevices;
end;
TConfig = class(TPersistent)
private
fListLines : TObjectList;
public
constructor Create;
destructor Destroy; override;
function AddLine(AName,AComPort:string):TLine;
procedure SaveConfig(AFileName:string);
procedure LoadConfig(AFileName:string);
published
property ListLines : TObjectList read fListLines write fListLines;
end;
TForm1 = class(TForm)
btnSave: TButton;
btnLoad: TButton;
btnCreate: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnCreateClick(Sender: TObject);
procedure btnLoadClick(Sender: TObject);
procedure btnSaveClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
Config:TConfig;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TLine }
function TLine.AddDevice(AName: string): TDevice;
begin
Result:=TDevice.Create(Self, AName, 1);
fListDevices.Add(Result);
end;
constructor TLine.Create(AConfig:TConfig;ANameLine,AComPort:string);
begin
fParentConfig:=AConfig;
fName:=ANameLine;
fComPort:=AComPort;
fListDevices:=TObjectList.Create;
end;
destructor TLine.Destroy;
begin
fListDevices.Free;
inherited;
end;
{ TConfig }
function TConfig.AddLine(AName,AComPort: string):TLine;
begin
Result:=TLine.Create(Self,AName,AComPort);
fListLines.Add(Result);
end;
constructor TConfig.Create;
begin
inherited;
fListLines:=TObjectList.Create;
end;
destructor TConfig.Destroy;
begin
fListLines.Free;
inherited;
end;
procedure TConfig.LoadConfig(AFileName: string);
var s:RawUTF8;
isValid: Boolean;
begin
s:=StringToUTF8(StringFromFile(AFileName));
JSONToObject(Self,@s[1],isValid);
if not isValid then ShowMessage('not valid');
end;
procedure TConfig.SaveConfig(AFileName: string);
var
s: string;
begin
s:=UTF8ToString(ObjectToJSON(Self,[woDontStoreDefault,woHumanReadable]));
FileFromString(s,AFileName);
end;
procedure TForm1.btnCreateClick(Sender: TObject);
var Line:TLine; Dev:TDevice;
begin
Line:=Config.AddLine('MyLine','COM1');
Line.AddDevice('MyDevice');
end;
procedure TForm1.btnLoadClick(Sender: TObject);
begin
Config.LoadConfig('test.cnfg');
end;
procedure TForm1.btnSaveClick(Sender: TObject);
begin
Config.SaveConfig('test.cnfg');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Config:=TConfig.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Config.Free;
end;
{ TDevice }
constructor TDevice.Create(ALine: TLine; AName: string;Adress:Integer);
begin
fParentLine:=ALine;
fName:=AName;
fAdress:=Adress;
end;
initialization
TJSONSerializer.RegisterClassForJSON([TLine, TDevice]);
finalization
Offline
There is no way of knowing which TObject instance is to be created when you read the JSON content.
Try to add woStoreClassName option, and register the corresponding class.
Please check the documentation of JSONToObject().
This is clearly stated AFAIR - see http://synopse.info/files/html/api-1.18 … ONTOOBJECT
Offline
this is my file
{
"ClassName":"TConfig",
"ListLines":
[{
"ClassName":"TLine",
"NameLine": "MyLine",
"ComPort": "COM1",
"IniFile": "",
"ListDevices":
[{
"ClassName":"TDevice",
"Name": "MyDevice",
"Speed": "9600",
"Adress": 1
}
]
}
]
}
there is field "classname", but it did not help.
The option "woStoreClassName" adds only property "TConfig" to the root object. Other options were earlier.
Offline
I have registred classes in initialization section
TJSONSerializer.RegisterClassForJSON([TLine, TDevice]);
Offline
It did not solve the problem. Then problem is that function Item := ClassInstanceCreate(ItemClass) doesn't call "create" method TLine object and therefore all of its properties equals nil.
Offline
You should change the class you inherit from.
Use TSynPersistent as parent class, and override its plain Create; virtual; constructor.
Also consider using TPersistentAutoCreateFields or TSynAutoCreateFields if you want the fields class instance to be initialized directly, without even the need to overwrite the constructor.
Offline
i used TSynPersistent and now its all works, though ealier i used TComponent as parent class, but it didn't work.
Thank you.
Offline
Pages: 1