Assuming there is a single root element (since it's a tree) you can use a very short recursive method to build the tree:
def process(id, src)
hash = src[id]
return { id: id } if hash.nil?
children = hash['children']
{ id: id, children: children.map { |child_id| process(child_id.to_s, src) } }
end
# the 'list' argument is the hash you posted, '6' is the key of the root node
json = process('6', list)
# json value:
#
# {:id=>"6", :children=>[
# {:id=>"8", :children=>[
# {:id=>"9", :children=>[
# {:id=>"7"}]},
# {:id=>"23"},
# {:id=>"24"}]},
# {:id=>"10", :children=>[
# {:id=>"12"},
# {:id=>"14"}]},
# {:id=>"11"}]}
I added the return { id: id } if hash.nil?
line since your input hash did not contain entries for children 7, 11, 12, 14, 23, 24. If their entries would be like below, you can remove that line.
"7" => { "children" => [] },
"11" => { "children" => [] },
"12" => { "children" => [] },
"14" => { "children" => [] },
"23" => { "children" => [] },
"24" => { "children" => [] }
In that case, the method would yield {:id=>"7", :children=>[]}
instead of {:id=>"7"}
which you can change if you wish by including a children.empty?
check and in that case return a hash with only an :id
key (like I do at the hash.nil?
check). However, in terms of consistency I would probably favor having the children
key present with an empty Array as value, rather than omitting it entirely.