#1 2021-12-11 13:21:20

Ghiber
Member
Registered: 2016-02-17
Posts: 14

error creating json

hello, I have created a small example to be able to generate demonstrate the error, before it worked in previous versions of mormot something happens now

Var
 Main:TDocVariantData;
 PArray1,PArray2,PArray3:PDocVariantData;



begin
  Main.Init();

  Main.AddValue('value0',10);

  Main.AddValue('object',_Obj([]));

  PArray1:=Main._[Main.AddValue('array1',_Arr([]))];
  PArray2:=Main._[Main.AddValue('array2',_Arr([]))];
  PArray3:=Main._[Main.AddValue('array3',_Arr([]))];

  PArray3.AddItem(_Obj(['value3',30]));
  PArray2.AddItem(_Obj(['value2',20]));
  PArray1.AddItem(_Obj(['value1',10]));

  writeln(Main.ToJSON());
  readln;
end.

the correct result expected in earlier versions of mormot 1 is this


{"value0": 10, "object": {}, "array1": [{"value1": 10}], "array2": [{"value2" : 20}], "array3": [{"value3": 30}]}


now in the latest version of mormot 1 is this


{"value0":10,"object":{},"array1":[],"array2":[],"array3":[{"value3":30}]}

Offline

#2 2021-12-11 13:28:23

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

Re: error creating json

Your code was not correct from the start, I am afraid.

You are calling AddValue() and putting the pointer into a local variable.
This works by change, because each time you call AdValue() the array location may change, so the pointer may be invalid.

Use indexes when you want to access a TDocVariantData.Values[] item using a pointer.

Offline

#3 2021-12-11 13:44:09

Ghiber
Member
Registered: 2016-02-17
Posts: 14

Re: error creating json

Thanks for your prompt response, I understand your answer and I had already done the test by using indexes, if it works, the strange thing is that I change the mormot to a previous version and if it works, but well I'll change it to work with indexes, and how the project is quite long I'm afraid I must check carefully, but I repeat before it worked.

Offline

#4 2021-12-11 18:35:27

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

Re: error creating json

It worked by chance.

The memory reallocation of a lot of structures, including TDocVariantData, has evolved with mORMot 2 for something more tuned in most cases.
This is why AddValue() behavior may have changed.

For your exact need, remember that you can nest the _ObjFast() and _ArrayFast() functions, and also that you can use '{' / '}' and '[' / ']' for adding items with some hierarchy.
Please check the doc again.

Offline

#5 2021-12-11 19:20:30

Ghiber
Member
Registered: 2016-02-17
Posts: 14

Re: error creating json

ab, sorry I already found the line that makes it work differently than what I expected,
here I show how it was before and how it is now, this change was made in one of your fixes.

function TDocVariantData.InternalAdd(const aName: RawUTF8): integer;
var len: integer;
begin
  if aName<>'' then begin
    if dvoIsArray in VOptions then
      raise EDocVariant.CreateUTF8('Add: Unexpected [%] object property in an array',[aName]);
    if not(dvoIsObject in VOptions) then begin
      VType := DocVariantVType; // may not be set yet
      include(VOptions,dvoIsObject);
    end;
  end else begin
    if dvoIsObject in VOptions then
      raise EDocVariant.Create('Add: Unexpected array item in an object');
    if not(dvoIsArray in VOptions) then begin
      VType := DocVariantVType; // may not be set yet
      include(VOptions,dvoIsArray);
    end;
  end;

********************************NOT WORK actual version mormot ************************
//  len := length(VValue);
//  if VCount>=len then begin
//    len := NextGrow(VCount);
//    SetLength(VValue,len);
//  end;
//  if aName<>'' then begin
******************************************************************



*************IT WORKS  previous version mormot*******************
  if VValue=nil then
    SetLength(VValue,16) else
    if VCount>=length(VValue) then
      SetLength(VValue,VCount+VCount shr 3+32);
  if aName<>'' then begin
    len := length(VValue);

*****************************************



    if Length(VName)<>len then
      SetLength(VName,len);
    if dvoInternNames in VOptions then begin // inlined InternNames method
      if DocVariantType.fInternNames=nil then
        DocVariantType.fInternNames := TRawUTF8Interning.Create;
      DocVariantType.fInternNames.Unique(VName[VCount],aName);
    end else
      VName[VCount] := aName;
  end;
  result := VCount;
  inc(VCount);
end;

Last edited by Ghiber (2021-12-11 19:22:23)

Offline

#6 2021-12-11 20:15:38

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

Re: error creating json

This is what I wrote: calling NextGrow() is a much better algorithm than the previous implementation.

Please follow the forum rules and don't post such code directly in the thread.

Offline

Board footer

Powered by FluxBB