#1 2025-09-26 11:09:03

DirkH
Member
Registered: 2025-09-26
Posts: 5

lists in objects to Json

Hello, everyone

I want to store and retrieve the data of an object with a list property in a json string. However I have a hard time getting this to work. I would appreciate some hints were I can find examples or if it is a good practice using a list instead of an array at all.

Thanks and best regards

My current failing example code:

  TItem = Record
    Name: String;
  End;

  TStorage = Class
  Private
    fPlace: RawUtf8;
    fItems: IList < TItem > ;
  Published
    Property Place: RawUtf8 Read fPlace Write fPlace;
    Property Items: IList < TItem > Read fItems Write fItems;
  End; 
[...]
Procedure TForm1.Button1Click(Sender: TObject);
Var
  Storage: TStorage;
  Item: TItem;
Begin
  Storage := TStorage.Create;
  Storage.Place := 'Ocean';
  Storage.Items := Collections.NewPlainList < TItem > ;

  Item.Name := 'Foo';
  Storage.Items.Add(Item);
  Item.Name := 'Bar';
  Storage.Items.Add(Item);

  Memo1.text := ObjectToJson(Storage, [woHumanReadable]);      //does not print Items
End;      

Last edited by DirkH (2025-09-26 11:10:29)

Offline

#2 2025-09-26 16:01:39

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 15,224
Website

Re: lists in objects to Json

Try with the mORMot collections.

Or even easier, with a dynamic array of record.
Here collections are clearly an overhead.

Please also which compiler do you use, to be sure we have enough context.

Offline

#3 2025-09-27 10:40:58

DirkH
Member
Registered: 2025-09-26
Posts: 5

Re: lists in objects to Json

Thank you for you answer,

I'm lost in some rabbit hole wink Every hour I'm working with it I'm more confused.
I'm using Lazarus 4.2 FPC 3.2.2

At least for now I put everything into records, and used TArray instead of IList. My best guess so far is documented at https://github.com/D-H-R/mormot_json/bl … /unit1.pas.
I know that RecordSaveJson is supposed to do base64 encoding, I wasn't able to get s.th. else running sad

As you might have expected I need a human readable format.

Can you please point out to me which classes (for data holding) and functions for the "toJson" I should use for a first approach.

Thank you so much.

Last edited by DirkH (2025-09-27 10:45:49)

Offline

#4 2025-09-29 07:28:40

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 15,224
Website

Re: lists in objects to Json

FPC does not have RTTI about extended record.
This is a FPC limitation. (the FPC trunk supports extended records RTTI and mORMot can use it).

So you need to follow
https://synopse.info/forum/viewtopic.php?pid=36191

A quick search in the forum find it, and also similar answers like:
https://synopse.info/forum/viewtopic.php?id=6994

Even grok is almost write about this point:
https://grok.com/share/c2hhcmQtMg%3D%3D … b7156e9191
"Almost" because the source code and text definition format is incorrect wink But at least you have the idea.
And it is really funny how grok is even more hallucinating, the more you give him corrections.

Offline

#5 2025-09-29 09:39:23

flydev
Member
From: France
Registered: 2020-11-27
Posts: 127
Website

Re: lists in objects to Json

I have provided you with examples there last day: D-H-R/mormot_json/issues/1


ab wrote:

And it is really funny how grok is even more hallucinating, the more you give him corrections.

I admit I feel like the more thinking they try to do, the more they tend to hallucinate...

Offline

#6 2025-10-01 07:13:27

DirkH
Member
Registered: 2025-09-26
Posts: 5

Re: lists in objects to Json

Thanks to both of you and especially flydev for this turnkey solution - superb!

Now I'm running into the next Issue I dont understand. Since JSON creation works so great I'm trying to read it back.
ObjLoadJson works fine if JSON and Object structure exactly match. However I need to tolerate if it is (slightly) modified by the user or if there is an update in the structure I need to read an old one or introduce new fields.

I wanted to do that with TDocVaraiant, but I cant Acces fields in the "measurementData" array of objects.

TDocVariantData(item).S['note'] fails in mormot.core.variants TDocVariantData.GetValueIndex because it expects cardinal(VType) = DocVariantVType, which is in my case (16396 = 271, obviously fail -> result-1)

procedure TForm1.Button9Click(Sender: TObject);
Var
  doc: variant;
  item: variant;
Begin
  doc := _Json('{"text":"Some general Description","measurementData":[{"id":47,"note":"erster Teil","values":[1.1,1.2,1.3]},{"id":11,"note":"zweiter Teil","values":[2.1,2.2,2.3]}]}');
  item := TDocVariantData(doc).A['measurementData'].Value[1];

  Memo2.Lines.Clear;
  Memo2.lines.add('Raw second element: ' + VariantToUtf8(TDocVariantData(doc).A['measurementData'].Value[1]));    //returns {"id":11,"note":"zweiter Teil","values":[2.1,2.2,2.3]}
  Memo2.lines.add('note: ' + TDocVariantData(item).S['note']);  //fails "property note not found"
End;  

Offline

#7 2025-10-01 08:08:04

flydev
Member
From: France
Registered: 2020-11-27
Posts: 127
Website

Re: lists in objects to Json

Personal taste, I feel more comfortable using IDocDict/List. Maybe take a look at this blog post if it helps (check the advanced features: filtering, searching):

https://blog.synopse.info/?post/2024/02 … hi-and-FPC

Offline

#8 2025-10-01 08:44:11

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 15,224
Website

Re: lists in objects to Json

As documented, do not use TDocVariantData() but _Safe() when trans-typing such values.
Or use item: PDocVariantData directly instead of a local variant value.

Since you seem to be lost in variant/TDocVariant internals (those are not easy to grasp), consider IDocList/IDocDict instead, as FlyDev proposed.
smile

Offline

#9 2025-10-01 14:01:17

DirkH
Member
Registered: 2025-09-26
Posts: 5

Re: lists in objects to Json

I have not yet all my use cases covered but the question how to access "note" from the inner ojbect is solved:
I used IDocList / Dict and it works like a breeze big_smile

dict := DocDict('{"text":"Some general Annot. Description","measurementData":[{"id":47,"note":"erster Teil","values":[1.1,1.2,1.3]},{"id":11,"note":"zweiter Teil","values":[2.1,2.2,2.3]}]}');
Memo2.lines.add('oneliner note' + dict.GetL('measurementData').GetD(1).GetS('note')); 

Last edited by DirkH (2025-10-01 14:02:23)

Offline

#10 2025-10-02 07:05:31

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 15,224
Website

Re: lists in objects to Json

Note you can just write:

Memo2.lines.add('oneliner note' + dict.L['measurementData'].D[1].S['note']); 

or

dict.PathDelim := '.';
Memo2.lines.add('oneliner note' + dict.S['measurementData.1.note']); 

Note that you could also use TDocVariantData.GetVariantByPath or P[]:

var doc: variant;
begin
  doc := _JsonFast('{...}');
  Memo2.lines.add('oneliner note' + _Safe(doc)^.P['measurementData.1.note']); 

or, using a TDocVariantData

var doc: TDocVariantData;
begin
  doc.InitJson('{...}');
  Memo2.lines.add('oneliner note' + doc.P['measurementData.1.note']); 

Offline

#11 2025-10-02 07:59:35

DirkH
Member
Registered: 2025-09-26
Posts: 5

Re: lists in objects to Json

Thanks a lot!

Somehow my brain doesn't like the square braces for this purpose. It seems to be linked to "access array / list element by position / memory offset" (I have to look at much C Code for embedded Systems). I think in this place the GetS() is exactly the same. Are there other places where it's worth to untie my brains knot ?

dict.PathDelim := '.';
Memo2.lines.add('short oneliner: ' + dict.GetS('measurementData.1.note'));      

Best regards

Last edited by DirkH (2025-10-02 08:02:26)

Offline

Board footer

Powered by FluxBB