44require 'jsonpath/enumerable'
55require 'jsonpath/version'
66
7+ # JsonPath: initializes the class with a given JsonPath and parses that path
8+ # into a token array.
79class JsonPath
8-
9- PATH_ALL = '$..*'
10+ PATH_ALL = '$..*' . freeze
1011
1112 attr_accessor :path
1213
1314 def initialize ( path , opts = nil )
1415 @opts = opts
1516 scanner = StringScanner . new ( path )
1617 @path = [ ]
17- while not scanner . eos?
18- if token = scanner . scan ( /\$ / )
19- @path << token
20- elsif token = scanner . scan ( /@/ )
18+ until scanner . eos?
19+ if token = scanner . scan ( /\$ |@\B |\* |\. \. / )
2120 @path << token
22- elsif token = scanner . scan ( /[a-zA-Z0-9_ -]+/ )
21+ elsif token = scanner . scan ( /[\$ @ a-zA-Z0-9:_ -]+/ )
2322 @path << "['#{ token } ']"
2423 elsif token = scanner . scan ( /'(.*?)'/ )
2524 @path << "[#{ token } ]"
2625 elsif token = scanner . scan ( /\[ / )
27- count = 1
28- while !count . zero?
29- if t = scanner . scan ( /\[ / )
30- token << t
31- count += 1
32- elsif t = scanner . scan ( /\] / )
33- token << t
34- count -= 1
35- elsif t = scanner . scan ( /[^\[ \] ]+/ )
36- token << t
37- elsif scanner . eos?
38- raise ArgumentError , 'unclosed bracket'
39- end
40- end
41- @path << token
26+ @path << find_matching_brackets ( token , scanner )
4227 elsif token = scanner . scan ( /\] / )
4328 raise ArgumentError , 'unmatched closing bracket'
44- elsif token = scanner . scan ( /\. \. / )
45- @path << token
4629 elsif scanner . scan ( /\. / )
4730 nil
48- elsif token = scanner . scan ( /\* / )
49- @path << token
5031 elsif token = scanner . scan ( /[><=] \d +/ )
5132 @path . last << token
5233 elsif token = scanner . scan ( /./ )
@@ -55,6 +36,24 @@ def initialize(path, opts = nil)
5536 end
5637 end
5738
39+ def find_matching_brackets ( token , scanner )
40+ count = 1
41+ until count . zero?
42+ if t = scanner . scan ( /\[ / )
43+ token << t
44+ count += 1
45+ elsif t = scanner . scan ( /\] / )
46+ token << t
47+ count -= 1
48+ elsif t = scanner . scan ( /[^\[ \] ]+/ )
49+ token << t
50+ elsif scanner . eos?
51+ raise ArgumentError , 'unclosed bracket'
52+ end
53+ end
54+ token
55+ end
56+
5857 def join ( join_path )
5958 res = deep_clone
6059 res . path += JsonPath . new ( join_path ) . path
@@ -70,19 +69,21 @@ def first(obj_or_str, *args)
7069 end
7170
7271 def enum_on ( obj_or_str , mode = nil )
73- JsonPath ::Enumerable . new ( self , self . class . process_object ( obj_or_str ) , mode , @opts )
72+ JsonPath ::Enumerable . new ( self , self . class . process_object ( obj_or_str ) , mode ,
73+ @opts )
7474 end
7575 alias_method :[] , :enum_on
7676
7777 def self . on ( obj_or_str , path , opts = nil )
78- self . new ( path , opts ) . on ( process_object ( obj_or_str ) )
78+ new ( path , opts ) . on ( process_object ( obj_or_str ) )
7979 end
8080
8181 def self . for ( obj_or_str )
8282 Proxy . new ( process_object ( obj_or_str ) )
8383 end
8484
8585 private
86+
8687 def self . process_object ( obj_or_str )
8788 obj_or_str . is_a? ( String ) ? MultiJson . decode ( obj_or_str ) : obj_or_str
8889 end
0 commit comments