You've got to separate issues here--one of retrieving the data, and the second of serializing it to JSON. They're related, but perhaps easier to solve if you mentally think of them as distinct problems.
Since you're storing the data as an adjacency list, then you'll need to either use a recursive function or a while loop to traverse the database up/down levels of the tree. There's no avoiding that unfortunately. (Technically if you know the maximum depth of the tree you could use a for loop, but I would never do that because it isn't future-proof.)
AFAIK MySQL doesn't support Recursive CTEs--there are some hacks posted on StackOverflow, but it'll almost certainly be eaiser to do this within your app (although slow because for each level of the tree you're issuing a new query, processing it within your app, and then re-issuing a new query for the next level up or down the tree).
For serializing the data as nested JSON, I hear good things about marshmallow's support for nested json. You could certainly write your own function, it's just Marshmallow provides some niceties like allowing you to specify the maximum nesting depth:
https://github.com/marshmallow-code/marshmallow/issues/9
If I were doing it, my first prototype would probably write two functions--one that maps the adjacency list in SQL to an equivalent list of lists in Python, and then a second that unwraps the python lists and serializes them into nested marshmallow json. From there it'll be easier to decide if it's worthwhile to eliminate the python lists of lists by doing the serializing inline with traversing the adjacency list.