It sounds like you could have benefited from a way to express pattern matching using JSON syntax, for destructuring a JSON object, and to represent the synthesis of new JSON using a "JSON quasiquote".
E.g. Lisp transformation with classic destructuring-bind and backquote:
(destructuring-bind (a (b (c &rest d) e) f (g h)) some-obj
`((,a ,b) ,c (,@d 1 2 3 ,e) (,f ,g, h)))
There are pattern matching libraries nowadays that do a lot more than destructuring-bind, but it illustrates the basic point.The destructuring-bind macro writes the code to pull apart some-obj according to the tree picture with embedded variables. The backquote syntax generates the code whose evaluation synthesizes the new tree object according to a template, with the values of expressions indicated by , and ,@ substituted and spliced into the template.
It did get me thinking, though, so I appreciate the advice. I'm wondering now how to port that idea to Ruby.
(Why almost: because "destructuring lambda lists" don't support the environment parameter of macro lambda lists!)
I had to write a library to transform JSON from one shape into another, carrying over the values but placing them in different nodes on a new tree. I found that thinking in terms of tree transformations was incredibly hard. The way I solved it was by flattening the JSON, transforming the flattened version, and when I'm done, inflating it back up.
In other words, working with the simpler, "2D" version of a JSON was much simpler than its "3D" tree structure, and writing flatten/unflatten independent from the transforming code was a nice modularity bonus.
It's really all about decomposing the problem and solving its parts.