#1 2017-03-22 19:35:20

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Use JSONToObject for tree structure

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?

Offline

#2 2017-03-22 19:49:33

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,662
Website

Re: Use JSONToObject for tree structure

Register the ObjArray.

Offline

#3 2017-03-22 19:51:02

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 337

Re: Use JSONToObject for tree structure

You can try my SynJSONTreeView https://drive.google.com/open?id=0Bx7LP … 0p2eWxNUUE, but not implemented/tested for FPC.

Best regards.


Esteban

Offline

#4 2017-03-22 22:19:26

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Re: Use JSONToObject for tree structure

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.    

Offline

#5 2017-03-23 17:16:02

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Re: Use JSONToObject for tree structure

Am I missing an obvious point?

Offline

#6 2017-03-24 08:18:05

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,662
Website

Re: Use JSONToObject for tree structure

Naming the property 'Childs' instead of 'Items' may help... to follow JSON layout...
sad

Also use TSynAutoCreateFields as root class, if you want built-in management of the T*ObjArray content.

The correct way of implementing it may be:

program test;

uses
  {$I SynDprUses.inc} // use FastMM4 on older Delphi, or set FPC threads
  Classes,
  SysUtils,
  SynCommons,
  mORMot;

type
  TItem = class;
  TItemObjArray = array of TItem;

  { TItem }

  TItem = class(TSynAutoCreateFields)
  private
    FID: integer;
    FChilds: TItemObjArray;
  published
    property ID: integer read FID write FID;
    property Childs: TItemObjArray read FChilds write FChilds;
  end;

procedure TestIt;
var
  it: TItem;
  s: RawUTF8;
begin
  TJSONSerializer.RegisterObjArrayForJSON([TypeInfo(TItemObjArray), TItem]);
  s := StringFromFile('test.json');
  it := TItem.Create;
  ObjectLoadJSON(it, s);
  ObjectToJSONFile(it, 'output.json');
  it.Free;
end;

begin
  TestIt;
end.

I have to enhance the documentation about T*ObjArray process...

Offline

#7 2017-03-24 09:59:10

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Re: Use JSONToObject for tree structure

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.

Offline

#8 2017-03-24 10:10:53

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,662
Website

Re: Use JSONToObject for tree structure

There is no need to name the type T*ObjArray - you can name it whatever you need.

It is just a convention to state that it has been registered via TJSONSerializer.RegisterObjArrayForJSON.
To be sure that you can use it as published array type for proper JSON serialization for ORM and SOA.

Offline

#9 2017-03-24 10:28:01

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Re: Use JSONToObject for tree structure

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.

Offline

#10 2017-03-24 10:33:11

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Re: Use JSONToObject for tree structure

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

Offline

#11 2017-03-24 11:18:47

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Re: Use JSONToObject for tree structure

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?

Last edited by mohsenti (2017-03-24 11:28:29)

Offline

#12 2017-03-24 14:45:36

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Re: Use JSONToObject for tree structure

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?

Offline

#13 2017-03-24 15:15:49

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,662
Website

Re: Use JSONToObject for tree structure

If you have null in the JSON, I guess the property won't have its instance created, and would be nil.

Offline

#14 2017-03-24 15:49:02

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Re: Use JSONToObject for tree structure

I will create separate topics for these questions for better order for future.

Offline

#15 2017-03-24 16:07:29

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Offline

Board footer

Powered by FluxBB