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]);
finalizationOffline
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