class JsonPath

Constants

VERSION

Attributes

expression[RW]
result[RW]
resultType[RW]

Public Class Methods

new(arg) click to toggle source
# File lib/json_path.rb, line 19
def initialize(arg)
  @resultType = arg && arg.resultType rescue "VALUE"
  @result = []
  @expression = normalize(arg).sub(/^\$;/,"")
end

Public Instance Methods

asPath(path) click to toggle source
# File lib/json_path.rb, line 37
def asPath(path)
  x = path.split(";")
  p = "$"

  i = 1
  n = x.size
  while i<n do
    p += /^[0-9*]+$/.match?(x[i]) ? ("["+x[i]+"]") : ("['"+x[i]+"']")
    i +=1
  end
  return p
end
jp_eval(x, _v, _vname) click to toggle source
# File lib/json_path.rb, line 149
def jp_eval(x, _v, _vname)
  begin
    if _v && _v.size > 0
      case _v
      when Hash
        x.match(/@.(\w+)\s*([<=>!~]*)\s*(\d*)/)
        case
        when !$3 || $3.size == 0
          _v[$1]
        else
          value = $1 == "length" ? _v.size : _v[$1].to_i
          value.send($2,$3.to_i)
        end
      when Array
        x.match(/@.(\w+)\s*([\<\=\>\!\~\-\+]+)\s*(\d*)/)
        case
        when (!$3 || $3.size == 0) && $1 && $1.is_i?
          _v[$1.to_i]
        else
          value = case $1
          when "length"
            _v.size
          when /\A[-+]?\d+\z/
            $1.to_i
          end
          value && value.send($2,$3.to_i)
        end
      end

    end
  rescue Exception => e
    raise "jsonPath: " + e.message + ": " + x.gsub(/@/, "_v").gsub(/\^/, "_a")
  end
end
normalize(expr) click to toggle source
# File lib/json_path.rb, line 25
def normalize(expr)
  subx = [];
  
  ex = expr.gsub(/[\['](\??\(.*?\))[\]']/){ |x| subx << $1; "[##{subx.size - 1}]"}
  ex = ex.gsub(/'?\.'?|\['?/, ";")
  ex = ex.gsub(/;;;|;;/, ";..;")
  ex = ex.gsub(/;$|'?\]|'$/, "")
  ex = ex.gsub(/#([0-9]+)/){ |x| subx[$1.to_i]}

  ex
end
on(object) click to toggle source
# File lib/json_path.rb, line 184
def on(object)
  if @expression && object && ( @resultType == "VALUE" || @resultType == "PATH")
    trace(@expression, object, "$")
    return @result || false
  end
end
slice(loc, expr, val, path) click to toggle source
# File lib/json_path.rb, line 125
def slice(loc, expr, val, path)
  if Array === val
    len=val.size
    start=0
    size=len
    step=1

    loc.gsub(/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/) do |match|
      start = $1.to_i if $1.size > 0
      size  = $2.to_i if $2.size > 0
      step  = $3.to_i if $3.size > 0
    end

    start = (start < 0) ? [0,start+len].max : [len,start].min
    size  = (size < 0)  ? [0,size+len].max   : [len,size].min

    i = start
    while i < size
      trace(i.to_s+";"+expr.to_s, val, path)
      i += step
    end
  end
end
store(p, v) click to toggle source
# File lib/json_path.rb, line 50
def store(p, v)
  if p
    @result << (@resultType == "PATH" ? asPath(p) : v)
  end
  return !!p
end
trace(expr, val, path) click to toggle source
# File lib/json_path.rb, line 57
def trace(expr, val, path)
  if expr && expr.size > 0
    x = expr.split(";")
    loc = x.shift
    x = x.join(";")

    if val && (Hash === val && val[loc]) 
      trace(x, val[loc], path + ";" + loc)
    elsif val && (Array === val && loc && loc.is_i? && val.size > loc.to_i)
      trace(x, val[loc.to_i], path + ";" + loc)

    elsif (loc == "*")
      walk(loc, x, val, path) do |m,l,x,v,p|
        trace("#{m};#{x}",v,p)
      end

    elsif (loc == "..")
      trace(x, val, path)
      walk(loc, x, val, path) do |m,l,x,v,p|
        case object = v[m]
        when Hash,Array
          trace("..;"+x.to_s,v[m],p.to_s+";"+m.to_s)
        end
      end

    elsif /,/.match?(loc) # [name1,name2,...]
      s=loc.split(/'?,'?/)
      i=0
      n=s.size

      while  i<n do
        trace(s[i].to_s+";"+x.to_s, val, path)
        i+=1
      end

    elsif (/^\(.*?\)$/.match?(loc)) # [(expr)]
      last_idx = path.rindex(";") + 1
      p = path[last_idx..-1]
      trace(jp_eval(loc, val, p).to_s+";"+x, val, path)

    elsif (/^\?\(.*?\)$/.match?(loc)) # [?(expr)]
      walk(loc, x, val, path) do |m,l,x,v,p| 
        if jp_eval(l.sub(/^\?\((.*?)\)$/,'\1'),v[m],m)
          trace("#{m};#{x}",v,p)
        end
      end

    elsif (/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.match?(loc)) # [start:end:step]  python slice syntax
      slice(loc, x, val, path)
    end
  else
    store(path, val)
  end
end
walk(loc, expr, val, path) { |i,loc,expr,val,path| ... } click to toggle source
# File lib/json_path.rb, line 112
def walk(loc, expr, val, path)
  case val
  when Array
    val.each_with_index do |object,i|
      yield i,loc,expr,val,path
    end
  when Hash
    val.each_pair do |key,value|
      yield key,loc,expr,val,path
    end
  end
end