var JSONObject: TJSONObject; JSONArray: TJSONArray; ... JSONObject:=TJSONObject.ParseJSONValue(S) as TJSONObject; try JSONArray := JSONObject.Get(0).JsonValue as TJSONArray; try Memo1.Lines.Add(JSONArray.Get(0).ToString); finally FreeAndNil(JSONArray); // если это закомментировать то работает но JSONArray остается в памяти. end; finally FreeAndNil(JSONObject); // а если нет, то тут вылетает Invalid pointer operation end; 

After the JSONObject destroyed, you can access the JSONArray (if we did not forcefully destroy it before) the object will exist, but the structure and data of the JSON document itself will not be there anymore. The same with JSONObject , if you first destroy JSONArray How, then, is it correct to destroy them and free memory?

Here is an example of a JSON document:

 {"asks": [["0.01129999",0.9997237],["0.01130000",594.26412711],["0.01130826",0.23004724],["0.01130999",0.25231793]], "bids": [["0.01129800",174.30861783],["0.01128867",0.13287659],["0.01128817",0.0097447],["0.01127559",241.94881004]], "isFrozen":"0","seq":254407265 } 
  • Add your code, what does ".. that works but JSONArray remains in memory"? Questions asking for help with debugging (“why does this code not work?”) Should include the desired behavior, a specific problem or error, and a minimum code for playing it right in the question . - Kromster
  • It is necessary to destroy only JSONObject . What structure are you trying to parse? - zed
  • This means that if you exclude a line from the code with the array being deleted - FreeAndNil(JSONArray) then the error Invalid pointer operation will not occur when you destroy JSONObject , BUT after this destruction you can refer to JSONArray , for example: Memo1.Lines.Add(JSONArray.ClassParent.ClassName); From what I conclude that the object remains. - HeathRow
  • Do not access JSONArray after destroying JSONObject . - zed
  • Yes, I, in general, there is no need to refer to it, I JSONArray that in fact JSONArray not destroyed when JSONObject destroyed, as I was written above. - HeathRow

2 answers 2

You can use the ReportMemoryLeaksOnShutdown parameter, (you can read more here ) which will show whether there are memory leaks or not and which objects are not destroyed. In theory, after the destruction of JSONObject, everything should be cleared. It is even possible that you still have a "junk" link to the object of which no longer exists.

  • This is great advice, but unfortunately, this is a comment, not an answer to a question. - Kromster

The standard json parser is designed in such a way that during parsing, when you call the TJSONObject.ParseJSONValue method, it creates a hierarchy of objects for each json field and returns the root object through which you can access any field.

The created objects are inherited from the TJSONAncestor class and have the FOwned property, which is set to True (including for the root object).

When destroying the root object, it checks whether it owns the child objects and, if any, destroys them:

 destructor TJSONObject.Destroy; var Member: TJSONAncestor; I: Integer; begin if FMembers <> nil then begin for i := 0 to FMembers.Count - 1 do begin Member := TJSONAncestor(FMembers[I]); if Member.GetOwned then Member.Free; end; FreeAndNil(FMembers); end; inherited Destroy; end; 

Similarly, child objects, when destroyed, destroy their nested objects, if any.

Thus, it is enough for the user to call one destructor of the root object so that all created objects are freed.

Notice that in the line:

 JSONArray := JSONObject.Get(0).JsonValue as TJSONArray; 

there is no object creation , you only request from the root object a reference to the object that was created during the parsing of json . You can use it until the root object is destroyed. And, accordingly, in no case should you try to delete this requested object by hand.