lib/jsonpath/parser.rb in jsonpath-1.0.0 vs lib/jsonpath/parser.rb in jsonpath-1.0.1
- old
+ new
@@ -12,43 +12,43 @@
end
# parse will parse an expression in the following way.
# Split the expression up into an array of legs for && and || operators.
# Parse this array into a map for which the keys are the parsed legs
- # of the split. This map is then used to replace the expression with their
+ # of the split. This map is then used to replace the expression with their
# corresponding boolean or numeric value. This might look something like this:
# ((false || false) && (false || true))
- # Once this string is assembled... we proceed to evaluate from left to right.
- # The above string is broken down like this:
+ # Once this string is assembled... we proceed to evaluate from left to right.
+ # The above string is broken down like this:
# (false && (false || true))
# (false && true)
- # false
+ # false
def parse(exp)
exps = exp.split(/(&&)|(\|\|)/)
construct_expression_map(exps)
- @_expr_map.each {|k, v| exp.sub!(k, "#{v}")}
+ @_expr_map.each { |k, v| exp.sub!(k, v.to_s) }
raise ArgumentError, "unmatched parenthesis in expression: #{exp}" unless check_parenthesis_count(exp)
- while (exp.include?("("))
- exp = parse_parentheses(exp)
- end
+
+ exp = parse_parentheses(exp) while exp.include?('(')
bool_or_exp(exp)
end
# Construct a map for which the keys are the expressions
- # and the values are the corresponding parsed results.
+ # and the values are the corresponding parsed results.
# Exp.:
# {"(@['author'] =~ /herman|lukyanenko/i)"=>0}
# {"@['isTrue']"=>true}
def construct_expression_map(exps)
- exps.each_with_index do |item, index|
+ exps.each_with_index do |item, _index|
next if item == '&&' || item == '||'
+
item = item.strip.gsub(/\)*$/, '').gsub(/^\(*/, '')
@_expr_map[item] = parse_exp(item)
end
end
- # using a scanner break down the individual expressions and determine if
+ # using a scanner break down the individual expressions and determine if
# there is a match in the JSON for it or not.
def parse_exp(exp)
exp = exp.sub(/@/, '').gsub(/^\(/, '').gsub(/\)$/, '').tr('"', '\'').strip
scanner = StringScanner.new(exp)
elements = []
@@ -98,83 +98,84 @@
# @TODO: Remove this once JsonPath no longer supports ruby versions below 2.3
def dig(keys, hash)
return nil unless hash.is_a? Hash
return nil unless hash.key?(keys.first)
return hash.fetch(keys.first) if keys.size == 1
+
prev = keys.shift
dig(keys, hash.fetch(prev))
end
- # This will break down a parenthesis from the left to the right
- # and replace the given expression with it's returned value.
+ # This will break down a parenthesis from the left to the right
+ # and replace the given expression with it's returned value.
# It does this in order to make it easy to eliminate groups
# one-by-one.
def parse_parentheses(str)
opening_index = 0
closing_index = 0
- (0..str.length-1).step(1) do |i|
- if str[i] == '('
- opening_index = i
- end
+ (0..str.length - 1).step(1) do |i|
+ opening_index = i if str[i] == '('
if str[i] == ')'
closing_index = i
break
end
end
- to_parse = str[opening_index+1..closing_index-1]
+ to_parse = str[opening_index + 1..closing_index - 1]
- # handle cases like (true && true || false && true) in
+ # handle cases like (true && true || false && true) in
# one giant parenthesis.
top = to_parse.split(/(&&)|(\|\|)/)
- top = top.map{|t| t.strip}
+ top = top.map(&:strip)
res = bool_or_exp(top.shift)
top.each_with_index do |item, index|
case item
when '&&'
res &&= top[index + 1]
when '||'
res ||= top[index + 1]
end
end
- # if we are at the last item, the opening index will be 0
+ # if we are at the last item, the opening index will be 0
# and the closing index will be the last index. To avoid
# off-by-one errors we simply return the result at that point.
- if closing_index+1 >= str.length && opening_index == 0
- return "#{res}"
+ if closing_index + 1 >= str.length && opening_index == 0
+ return res.to_s
else
- return "#{str[0..opening_index-1]}#{res}#{str[closing_index+1..str.length]}"
+ return "#{str[0..opening_index - 1]}#{res}#{str[closing_index + 1..str.length]}"
end
end
- # This is convoluted and I should probably refactor it somehow.
- # The map that is created will contain strings since essentially I'm
+ # This is convoluted and I should probably refactor it somehow.
+ # The map that is created will contain strings since essentially I'm
# constructing a string like `true || true && false`.
# With eval the need for this would disappear but never the less, here
- # it is. The fact is that the results can be either boolean, or a number
+ # it is. The fact is that the results can be either boolean, or a number
# in case there is only indexing happening like give me the 3rd item... or
# it also can be nil in case of regexes or things that aren't found.
# Hence, I have to be clever here to see what kind of variable I need to
# provide back.
def bool_or_exp(b)
- if "#{b}" == 'true'
+ if b.to_s == 'true'
return true
- elsif "#{b}" == 'false'
+ elsif b.to_s == 'false'
return false
- elsif "#{b}" == ""
+ elsif b.to_s == ''
return nil
end
+
b = Float(b) rescue b
b
end
# this simply makes sure that we aren't getting into the whole
- # parenthesis parsing business without knowing that every parenthesis
+ # parenthesis parsing business without knowing that every parenthesis
# has its pair.
def check_parenthesis_count(exp)
- return true unless exp.include?("(")
+ return true unless exp.include?('(')
+
depth = 0
exp.chars.each do |c|
if c == '('
depth += 1
elsif c == ')'