I am using delphi 10.2 with implicit JSON libraries like JSON, JSON.Readers, JSON.Types and having an error while trying to free the root json object.
Since my code is complicated.. to simulate same error i made a little event as;
procedure TForm1.Button1Click(Sender: TObject);
var
aJsonObj,aJsonObj2,aJsonObj3 : TJsonObject;
aJsonArr : TJsonArray;
begin
aJsonObj := TJsonObject.Create;
aJsonObj2 := TJsonObject.Create;
aJsonObj3 := TJsonObject.Create;
aJsonArr := TJsonArray.Create;
aJsonObj2.AddPair('aa','aa');
aJsonObj3.AddPair('bbb','bbb');
aJsonArr.Add(aJsonObj2);
aJsonArr.Add(aJsonObj3);
aJsonObj.AddPair('arr',aJsonArr);
aJsonObj.AddPair('a',aJsonObj2);
aJsonObj.AddPair('b',aJsonObj3);
ShowMessage(aJsonObj.ToJSON);
FreeAndNil(aJsonObj);
end;
i know.. im using the same object inside the object twice.. and thats what i want to cover. must i create my own recursive "DestroyJSONObject" procedure or is there another more elegant way?
I am using delphi 10.2 with implicit JSON libraries like JSON, JSON.Readers, JSON.Types and having an error while trying to free the root json object.
Since my code is complicated.. to simulate same error i made a little event as;
procedure TForm1.Button1Click(Sender: TObject);
var
aJsonObj,aJsonObj2,aJsonObj3 : TJsonObject;
aJsonArr : TJsonArray;
begin
aJsonObj := TJsonObject.Create;
aJsonObj2 := TJsonObject.Create;
aJsonObj3 := TJsonObject.Create;
aJsonArr := TJsonArray.Create;
aJsonObj2.AddPair('aa','aa');
aJsonObj3.AddPair('bbb','bbb');
aJsonArr.Add(aJsonObj2);
aJsonArr.Add(aJsonObj3);
aJsonObj.AddPair('arr',aJsonArr);
aJsonObj.AddPair('a',aJsonObj2);
aJsonObj.AddPair('b',aJsonObj3);
ShowMessage(aJsonObj.ToJSON);
FreeAndNil(aJsonObj);
end;
i know.. im using the same object inside the object twice.. and thats what i want to cover. must i create my own recursive "DestroyJSONObject" procedure or is there another more elegant way?
Share Improve this question asked Mar 10 at 15:33 Serkan EkşioğluSerkan Ekşioğlu 2615 silver badges16 bronze badges2 Answers
Reset to default 3All descendants of TJSONAncestor
provide a property Owned
allowing the container to free the instance. If you don't want that, set Owned
to False for all instances you want to manage yourself.
Your root aJsonObj
has references to aJsonObj2
and aJsonObj3
, and a reference to aJsonArr
which also has references to aJsonObj2
and aJsonObj3
.
As such, when aJsonObj
is freed, it will free aJsonArr
, which will free aJsonObj2
and aJsonObj3
, and then aJsonObj
will try to free aJsonObj2
and aJsonObj3
again and crash.
You have two choices:
use a separate
TJSONObject
instance for every object in the JSON. Don't share references.procedure TForm1.Button1Click(Sender: TObject); var aJsonObj, aJsonObj2, aJsonObj2b, aJsonObj3, aJsonObj3b: TJsonObject; aJsonArr : TJsonArray; begin aJsonObj := TJsonObject.Create; aJsonObj2 := TJsonObject.Create; aJsonObj3 := TJsonObject.Create; aJsonArr := TJsonArray.Create; aJsonObj2.AddPair('aa','aa'); aJsonObj3.AddPair('bbb','bbb'); aJsonArr.Add(aJsonObj2); aJsonArr.Add(aJsonObj3); aJsonObj.AddPair('arr',aJsonArr); aJsonObj2b := aJsonObj2.Clone as TJsonObject; // <-- add this aJsonObj.AddPair('a',aJsonObj2b); aJsonObj3b := aJsonObj3.Clone as TJsonObject; // <-- add this aJsonObj.AddPair('b',aJsonObj3b); ShowMessage(aJsonObj.ToJSON); FreeAndNil(aJsonObj); end;
if you must share references, then set
Owned=false
onaJsonObj2
andaJsonObj3
, and then free them explicitly yourself.procedure TForm1.Button1Click(Sender: TObject); var aJsonObj,aJsonObj2,aJsonObj3 : TJsonObject; aJsonArr : TJsonArray; begin aJsonObj := TJsonObject.Create; aJsonObj2 := TJsonObject.Create; aJsonObj2.Owned := False; // <-- add this aJsonObj3 := TJsonObject.Create; aJsonObj3.Owned := False; // <-- add this aJsonArr := TJsonArray.Create; aJsonObj2.AddPair('aa','aa'); aJsonObj3.AddPair('bbb','bbb'); aJsonArr.Add(aJsonObj2); aJsonArr.Add(aJsonObj3); aJsonObj.AddPair('arr',aJsonArr); aJsonObj.AddPair('a',aJsonObj2); aJsonObj.AddPair('b',aJsonObj3); ShowMessage(aJsonObj.ToJSON); FreeAndNil(aJsonObj); FreeAndNil(aJsonObj2); // <-- add this FreeAndNil(aJsonObj3); // <-- add this end;