You are not logged in.
Hi,
Is it OK that I inherit classes that I use with JSONToObject? I guess yes it is. but a simple problem is here, ObjectToJSONFile saves published properties in reverse order, from child to parent so If Parent has Prop1 and Prop2 and child add Prop3, ObjectToJSONFile save Prop3 and Prop2 and the Prop1.
I checked TTextWriterWriteObjectOption but it seems not has an option for this.
A sample for test:
program project1;
uses
Classes,
SysUtils,
FileUtil,
SynCommons,
mORMot;
type
TParentItem = class;
TParentItems = array of TParentItem;
{ TItem }
TItem = class(TSynAutoCreateFields)
private
FID: integer;
published
property ID: integer read FID write FID;
end;
TParentItem = class(TItem)
private
FChilds: TParentItems;
published
property Childs: TParentItems read FChilds write FChilds;
end;
procedure TestIt;
var
it: TParentItem;
s: RawUTF8;
begin
TJSONSerializer.RegisterObjArrayForJSON([TypeInfo(TParentItems), TParentItem]);
s := StringFromFile('test.json');
it := TParentItem.Create;
ObjectLoadJSON(it, s);
ObjectToJSONFile(it, 'output.json');
it.Free;
end;
begin
TestIt;
end.Input JSON:
{
"ID": 1,
"Childs": [{
"ID": 11,
"Childs": [{
"ID": 111,
"Childs": [{}, {}
]
}, {
"ID": 112,
"Childs": [{}, {}
]
}
]
}, {
"ID": 12,
"Childs": [{
"ID": 121,
"Childs": [{}, {}
]
}, {
"ID": 122,
"Childs": [{}, {}
]
}
]
}
]
}And output is:
{
"Childs":
[
{
"Childs":
[
{
"Childs":
[
{
"Childs": [],
"ID": 0
},
{
"Childs": [],
"ID": 0
}
],
"ID": 111
},
{
"Childs":
[
{
"Childs": [],
"ID": 0
},
{
"Childs": [],
"ID": 0
}
],
"ID": 112
}
],
"ID": 11
},
{
"Childs":
[
{
"Childs":
[
{
"Childs": [],
"ID": 0
},
{
"Childs": [],
"ID": 0
}
],
"ID": 121
},
{
"Childs":
[
{
"Childs": [],
"ID": 0
},
{
"Childs": [],
"ID": 0
}
],
"ID": 122
}
],
"ID": 12
}
],
"ID": 1
}As you can see it will write "Childs" first and then "ID".
Is there a way to make it sort in order or I should make a custom serializer?
Hi,
If I add j2oIgnoreUnknownProperty to JSONToObject options it will continue to read the JSON but it whould be nice to have an output from errors or problems. I looked at the code an it will just exit if it faces to any issue, can we have a call back event for error/warning ?
I can implement one if its ok.
Hi,
Is there a way to prevent making classes that their object do not exists in the JSON? In my JSON input sometimes the property that is a class does not exists and JSONToObject make a class for that with empty properties, can I set it to do not make an object and just pass nil to it? or I should make a custom serializer?
Here is a sample file:
{
"ID": 1,
"Childs": [{
"ID": 11,
"Childs": [{
"ID": 111,
"Childs": [{}, {}
]
}, {
"ID": 112,
"Childs": [{}, {}
]
}
]
}, {
"ID": 12,
"Childs": [{
"ID": 121,
"Childs": [{}, {}
]
}, {
"ID": 122,
"Childs": [{}, {}
]
}
]
}
],
"Options": {
"Name": "Name1"
}
}As you can see this is a tree but only parent has "Options" and if I write serializer like below it will make Options class for every child with empty propertises like the output, can I prevent that or I should make a custom serializer? an option would be nice.
program project1;
uses
Classes,
SysUtils,
FileUtil,
SynCommons,
mORMot;
type
TItem = class;
TItems = array of TItem;
{ TOptions }
TOptions = class(TPersistent)
private
FName: string;
published
property Name: string read FName write FName;
end;
{ TItem }
TItem = class(TSynAutoCreateFields)
private
FID: integer;
FChilds: TItems;
FOptions: TOptions;
published
property ID: integer read FID write FID;
property Childs: TItems read FChilds write FChilds;
property Options: TOptions read FOptions;
end;
procedure TestIt;
var
it: TItem;
s: RawUTF8;
begin
TJSONSerializer.RegisterObjArrayForJSON([TypeInfo(TItems), TItem]);
s := StringFromFile('test.json');
it := TItem.Create;
ObjectLoadJSON(it, s);
ObjectToJSONFile(it, 'output.json');
it.Free;
end;
begin
TestIt;
end. And the output will be like:
{
"ID": 1,
"Childs":
[
{
"ID": 11,
"Childs":
[
{
"ID": 111,
"Childs":
[
{
"ID": 0,
"Childs": [],
"Options": {
"Name": ""
}
},
{
"ID": 0,
"Childs": [],
"Options": {
"Name": ""
}
}
],
"Options": {
"Name": ""
}
},
{
"ID": 112,
"Childs":
[
{
"ID": 0,
"Childs": [],
"Options": {
"Name": ""
}
},
{
"ID": 0,
"Childs": [],
"Options": {
"Name": ""
}
}
],
"Options": {
"Name": ""
}
}
],
"Options": {
"Name": ""
}
},
{
"ID": 12,
"Childs":
[
{
"ID": 121,
"Childs":
[
{
"ID": 0,
"Childs": [],
"Options": {
"Name": ""
}
},
{
"ID": 0,
"Childs": [],
"Options": {
"Name": ""
}
}
],
"Options": {
"Name": ""
}
},
{
"ID": 122,
"Childs":
[
{
"ID": 0,
"Childs": [],
"Options": {
"Name": ""
}
},
{
"ID": 0,
"Childs": [],
"Options": {
"Name": ""
}
}
],
"Options": {
"Name": ""
}
}
],
"Options": {
"Name": ""
}
}
],
"Options": {
"Name": "Name1"
}
}I will create separate topics for these questions for better order for future.
Hi again,
Is there a way to prevent making classes that their object do not exists in the JSON? In my JSON input sometimes the property that is a class does not exists and JSONToObject make a class for that with empty properties, can I set it to do not make an object and just pass nil to it? or I should make a custom serializer?
Another simple question,
Is it OK that I inherit classes that I use with JSONToObject? I guess yes it is. but a simple problem is here, ObjectToJSONFile saves published properties in reverse order, from child to parent so If Parent has Prop1 and Prop2 and child add Prop3, ObjectToJSONFile save Prop3 and Prop2 and the Prop1.
I checked TTextWriterWriteObjectOption but it seems not has an option for this.
Do you want me to make a sample to make it more clear?
Lazarus now has a Online Package Manager and it works well, you can add it or ask GetMem to add it for easy install. in Lazarus.
http://forum.lazarus.freepascal.org/ind … 297.0.html
Thanks again.
While I'm testing I faced to a problem, if my class has not all the JSON child it will not load all the childs. As documented I solved it with j2oIgnoreUnknownProperty, but can I add a warning to it so it will load but send me warnings?
I can implement it but I want to know your opinion.
Thanks ab,
Code has bugs indeed, but the error cause was my mORMot, I got it with fpcupdelux and it get the source from deprecated newpascal-ccr repository.
Now I solved it and everything goes well. Thank you very much.
A question out of curiosity: Is this a rule to name items like T*ObjArray, I changed it and everything seems good but because I read your posts in forum, I wanted to ask.
Am I missing an obvious point?
Thanks ab and EMartin.
ab if you talk about something like this:
TJSONSerializer.RegisterClassForJSON([TItem]); I done that and call the line before ObjectLoadJSON and because it didnt change the errorm I removed it.
I tested again like this and error still the same:
begin
s:=ReadFileToString('child.json');
it:=TItem.Create;
TJSONSerializer.RegisterClassForJSON([TItem]);
TJSONSerializer.RegisterObjArrayForJSON([TypeInfo(TItems), TItem]);
ObjectLoadJSON(it,s);
it.Free;
end. Hi,
I have a JSON sample like this:
{
"ID": 1,
"Childs": [{
"ID": 11,
"Childs": [{
"ID": 111,
"Childs": [{}, {}
]
}, {
"ID": 112,
"Childs": [{}, {}
]
}
]
}, {
"ID": 12,
"Childs": [{
"ID": 121,
"Childs": [{}, {}
]
}, {
"ID": 122,
"Childs": [{}, {}
]
}
]
}
]
}And a sample code in last NewPascal code:
program project1;
uses
Classes,
SysUtils,
FileUtil,
mORMot;
type
TItem = class;
TItems = array of TItem;
{ TItem }
TItem = class(TPersistent)
private
FID: integer;
FItems: TItems;
published
property ID: integer read FID write FID;
property Items: TItems read FItems write FItems;
end;
var
it: TItem;
s: String;
begin
s:=ReadFileToString('child.json');
it:=TItem.Create;
ObjectLoadJSON(it,s);
it.Free;
end.but I get a error like this:
Project project1 raised exception class 'ESynException' with message:
TJSONRecordTextDefinition.Create: TSynMapSymbol text definition is not accurate, or the type has not been defined as PACKED record: RTTI size is 5220048 bytes but text definition generated 12 bytes
I know there is a problem with my struture but how can I get JSON tree loaded?
Any comment dear @ab?
Why there is a need for that?
@ab with a package making new projects in Lazarus and mORMot will be easier with no need of adding paths.
Lazarus encourage using packages not adding paths.
It is good to have ab opinion.
Hi,
Is there any particular reason not having a Lazarus package?
Now for each project I should add path to units but with Lazarus package just adding a package is enough.
Any answer?
So the code will be like this:
program ProjectServer;
{$APPTYPE CONSOLE}
uses
SynCommons,
mORMot,
SysUtils,
mORMotHttpServer;
type
{ TServiceServer }
TServiceServer = class(TSQLRestServerFullMemory)
published
procedure Sum(Ctxt: TSQLRestServerURIContext);
end;
{ TServiceServer }
procedure TServiceServer.Sum(Ctxt: TSQLRestServerURIContext);
begin
Ctxt.Results([Ctxt['a'] + Ctxt['b']]);
end;
var
aModel: TSQLModel;
aRestServ: TSQLHttpServer;
aRest: TServiceServer;
aDef: TSQLHttpServerDefinition;
begin
aModel := TSQLModel.Create([]);
try
aDef := TSQLHttpServerDefinition.Create;
aDef.Https := False;
aDef.BindPort := '888';
aDef.EnableCORS := True;
aDef.WebSocketPassword := '';
aRest := TServiceServer.Create(aModel);
aRestServ := TSQLHttpServer.Create(aRest, aDef);
with aRest do
try
Write('Press [Enter] to close the server.');
readln;
finally
Free;
end;
finally
aRestServ.Free;
aDef.Free;
aModel.Free;
end;
end.Right?
Now some question to understand better how should I work:
1- Should I use this sample server on real server or I should make it work with Apache for example? Also for HTTPS?
2-Should I use it as this server or somehow make it a cgi? how?
3-Where can I read about make a simple authentication like a simple for example API key?
I tried to read the examples and doc but they are so easy or so complicated and I want to know "How to run a very simple API in my server with mORMot in real project". What are the steps?
Hi,
How can I make sample 06 with REST API server so I can get access with simple browser GET request like:
http://localhost:1234/API/sum?a=2&b=3
(Custom port and root is API)
I want that to make a simple API but use it in browser.
Do you mean something like:
myNode := TSQLNote.Create; myNode.Title := 'no title'; aServer.Add(myNote);?
Yes but can't access aServer in TServiceNote
function TServiceNote.addNote(Title, Body: RawUTF8): Boolean;
begin
// can't access aServer here
end;I don't know continuation and how to work with DB in interface based system.
Hi all;
I develop mormot server based on document and demos but I can't insert data to table with interface system;
thanks;
// interfaces.pas
unit Interfaces;
interface
uses SynCommons;
type
INote = interface(IInvokable)
['{4C284438-8107-4237-9932-F844472A0369}']
function addNote(Title,Body:RawUtf8):Boolean;
end;
implementation
uses mORMot;
initialization
TInterfaceFactory.RegisterInterfaces([TypeInfo(INote)]);
end.// models.pas
unit Models;
interface
uses mOrmot,SynCommons;
type
TSQLNote=class(TSQLRecord)
private
fTitle,fBody:RawUTF8;
public
function check:Boolean;
published
property Title:RawUTF8 read fTitle write fTitle;
property Body:RawUTF8 read fBody write fBody;
end;
function CreateModel:TSQLModel;
implementation
function CreateModel:TSQLModel;
begin
Result:=TSQLModel.Create([TSQLNote]);
end;
{ TSQLNote }
function TSQLNote.check: Boolean;
begin
Result:=True;
end;
end.// main.pas
unit Main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs,mORMot,mORMotHttpServer,MormotSQLite3,SynCommons,Interfaces,SynSQLite3Static;
type
TServiceNote=class(TInterfacedObject,INote)
public
function addNote(Title: RawUTF8; Body: RawUTF8): Boolean;
end;
TForm2 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
aModel: TSQLModel;
aServer: TSQLRestServer;
aHTTPServer: TSQLHttpServer;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
uses Models;
procedure TForm2.FormCreate(Sender: TObject);
begin
aModel:=CreateModel;
aServer:=TSQLRESTServerDB.Create(aModel,'Database.db');
aServer.ServiceDefine(TServiceNote,[INote],sicShared);
aHTTPServer:=TSQLHttpServer.Create('8096',aServer,'+',useHttpApiRegisteringURI);
end;
procedure TForm2.FormDestroy(Sender: TObject);
begin
aModel.Free; aServer.Free; aHTTPServer.Free;
end;
{ TServiceDemo }
function TServiceNote.addNote(Title, Body: RawUTF8): Boolean;
begin
end;
end.