module JsonWalk


Module JsonWalk written by Ph. Jounin Sept 2016 Released under GPL version 2


jsonwalk.rb

walk through a json tree. This is slighlty different from classical tree parsing since json nodes are either hashes, arrays or leaves


Constants

VERBOSE
VERSION

Public Class Methods

IsAncestor( root, nodes ) click to toggle source

return true if one member of nodes is descendant of the tree beginning by root probably useless outside the module…

# File lib/jsonwalk.rb, line 21
def JsonWalk.IsAncestor( root, nodes ) 
        case root
        when Hash
                root.each do |k, v|
                        return true  if (nodes.include? v  or IsAncestor(v, nodes)) 
                end
        when Array
                root.each  do |v|
                        return true   if (nodes.include? v  or IsAncestor(v, nodes)) 
                end
        else
                return true if (nodes.include? root) 
        end
        return false
end
backward(parent,node) click to toggle source

move one step backward (but keep current selection)

# File lib/jsonwalk.rb, line 63
def  JsonWalk.backward(parent,node)
        return nil if parent==nil or node==nil
        return parent.select { |child| IsAncestor(child, node) }
end
forward(node, branch) click to toggle source

move forward in the tree, if node is a hash return on child if it is an array, return the set of children

# File lib/jsonwalk.rb, line 40
def JsonWalk.forward(node, branch)
        # move forward : get the uniq child or all of them
        return nil if node==nil
        return node.kind_of?(Array) ? node.flatten.map {|child| child[branch]} : node[branch] 
end
select(node, branch, condition, operator) click to toggle source

just select a set of children matching a condition this does not change the level in the tree

# File lib/jsonwalk.rb, line 48
def  JsonWalk.select(node, branch, condition, operator)
        # check manually, seems less dangerous than using eval
        case operator
        when '=='
                return node.flatten.select {|child| child[branch]==condition}
        when '=~'
                return node.flatten.select {|child| /#{condition}/.match(child[branch])}
        when '!='
                return node.flatten.select {|child| child[branch]!=condition}
        when '!~'
                return node.flatten.select {|child| not /#{condition}/.match(child[branch])}
        end
end
walk(root, path) click to toggle source

walk the json tree : root is the top of the tree returned by json.parse path is a list of keys to child nodes with either selection by value or backward steps

# File lib/jsonwalk.rb, line 71
def  JsonWalk.walk(root, path)

        levels = []           # keep track of how do we get to the current node
        nodes = root
        
        path.each do |child_key|
                case child_key 
                when Integer
                # just in case you want a fixed row
                        print "moving forward to index #{child_key}\n" if VERBOSE
                        nodes =  (nodes.class==Array and child_key<nodes.count) ? nodes[child_key] : nil
                when '..'
                        # move backwards, but keep only items which include a member of nodes in the sub tree
                        print "moving one step backward\n"             if VERBOSE
                        nodes = backward(levels.pop, nodes)         # levels.pop return the previous node
                when  /(==|=~|!=|!~)/
                        # this is a selection, regexp returns before, after and matching substrings
                        print "selecting nodes with key #{$`}, val #{$'}, cond #{$&}\n"  if VERBOSE
                        nodes = select( nodes,  $`, $', $& )
                else
                        # move deeper in the tree
                        print "moving forward to key #{child_key}\n"       if VERBOSE
                        levels.push nodes   # keep track of current level
                        nodes = forward( nodes, child_key)
                end
                
        end
        return nodes.class==Array ? nodes.compact : nodes
end