Module: JsonWalk

Defined in:
lib/jsonwalk.rb,
lib/jsonwalk/version.rb

Overview


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


Constant Summary collapse

VERBOSE =

traces ?

false
VERSION =
"1.1.2"

Class Method Summary collapse

Class Method Details

.backward(parent, node) ⇒ Object

move one step backward (but keep current selection)



63
64
65
66
# 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) ⇒ Object

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



40
41
42
43
44
# 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

.IsAncestor(root, nodes) ⇒ Object

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



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 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

.select(node, branch, condition, operator) ⇒ Object

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



48
49
50
51
52
53
54
55
56
57
58
59
60
# 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) ⇒ Object

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



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# 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