Depends. As long as the TJSONData descendant is still accessible, e.g. part of a JSON tree whose root are still accessible, there's no need to manually free every node. Freeing the root will free all of its children as well. The data structure holding the children (a TFP[Hash]ObjectList instance) is created with parameter true, which means its contents will be freed as soon as the instance is freed. Watch out for double free or Clone result, though.
Another solution, if you don't mind using FPC trunk and gc overhead, there's a libgc unit that implements memory manager based on Boehm GC.
you were absolutely right! I went through my code and made a bunch of changes, now the JSON related memory leak has gone! here are a few things I have learned
1. the ShowJSONData does not either create or remove nodes from a JSON structure, it merely maps the JSON leave pointers to a TTreeView. therefore, whenever one wants to modify the JSON data, he/she has to make modifications directly to the JSON data itself, then call ShowJSONData to refresh the pointer mappings. As you said, as long as the JSON leaves are accessible via some root object, a FreeAndNil() at the FormDestroy event will free everything.
2. Always use TJSONData/TJSONArray/TJSONObject's Add/Remove/assignment methods to add/remove/modify the JSON data structure. As long as you modify the main data structure using its own methods, the nodes' memories are managed.
3. A safe (yet a little bit inefficient) way to create/modify JSON sub-structure is to use strings - inside a function, one can create a JSON object, add all needed nodes, and then save as a string by JSONData.AsJSON, then you can FreeAndNil that object right away, and return the JSON string. In the calling function, use GetJSON() to recreate that object and attach it to the base JSON data. This way, each function becomes self-contained. It is easier to debug the memory leak.