jsonpath 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -45,4 +45,6 @@ As well, you can include it as a library.
45
45
  break price if price < 15.0
46
46
  end
47
47
  # => 8.95
48
- ~~~~~
48
+ ~~~~~
49
+
50
+ You can optionally prevent eval from being called on sub-expressions by passing in :allow_eval => false to the constructor.
data/lib/jsonpath.rb CHANGED
@@ -6,7 +6,8 @@ class JsonPath
6
6
 
7
7
  attr_reader :path
8
8
 
9
- def initialize(path)
9
+ def initialize(path, opts = nil)
10
+ @opts = opts
10
11
  scanner = StringScanner.new(path)
11
12
  @path = []
12
13
  bracket_count = 0
@@ -53,11 +54,11 @@ class JsonPath
53
54
  end
54
55
 
55
56
  def enum_on(object)
56
- JsonPath::Enumerable.new(self, object)
57
+ JsonPath::Enumerable.new(self, object, @opts)
57
58
  end
58
59
 
59
- def self.on(object, path)
60
- self.new(path).on(object)
60
+ def self.on(object, path, opts = nil)
61
+ self.new(path, opts).on(object)
61
62
  end
62
63
 
63
64
  end
@@ -2,58 +2,77 @@ class JsonPath
2
2
  class Enumerable
3
3
  include ::Enumerable
4
4
 
5
- def initialize(path, object)
6
- @path, @object = path.path, object
5
+ def initialize(path, object, options = nil)
6
+ @path, @object, @options = path.path, object, options
7
7
  end
8
8
 
9
9
  def each(node = @object, pos = 0, &blk)
10
- if pos == @path.size
11
- return blk.call(node)
12
- else
13
- case expr = @path[pos]
14
- when '*', '..'
15
- each(node, pos + 1, &blk)
16
- when '$'
17
- each(node, pos + 1, &blk) if node == @object
18
- when '@'
19
- each(node, pos + 1, &blk)
20
- when /^\[(.*)\]$/
21
- expr[1,expr.size - 2].split(',').each do |sub_path|
22
- case sub_path[0]
23
- when ?', ?"
24
- if node.is_a?(Hash)
25
- key = sub_path[1,sub_path.size - 2]
26
- each(node[key], pos + 1, &blk) if node.key?(key)
27
- end
28
- when ??
29
- (node.is_a?(Hash) ? node.keys : (0..node.size)).each do |e|
30
- subenum = ::JsonPath.new(sub_path[2,sub_path.size - 3]).on(node[e])
31
- each(node[e], pos + 1, &blk) if subenum.any?{|n| true}
32
- end
33
- else
34
- if node.is_a?(Array)
35
- @obj = node
36
- array_args = sub_path.gsub('@','@obj').split(':')
37
- start_idx = (array_args[0] && eval(array_args[0]) || 0) % node.size
38
- end_idx = (array_args[1] && eval(array_args[1]) || (sub_path.count(':') == 0 ? start_idx : -1)) % node.size
39
- step = array_args[2] && eval(array_args[2]) || 1
40
- (start_idx..end_idx).step(step) {|i| each(node[i], pos + 1, &blk)}
41
- end
10
+ return blk.call(node) if pos == @path.size
11
+ case expr = @path[pos]
12
+ when '*', '..'
13
+ each(node, pos + 1, &blk)
14
+ when '$'
15
+ each(node, pos + 1, &blk) if node == @object
16
+ when '@'
17
+ each(node, pos + 1, &blk)
18
+ when /^\[(.*)\]$/
19
+ expr[1,expr.size - 2].split(',').each do |sub_path|
20
+ case sub_path[0]
21
+ when ?', ?"
22
+ if node.is_a?(Hash)
23
+ key = sub_path[1,sub_path.size - 2]
24
+ each(node[key], pos + 1, &blk) if node.key?(key)
25
+ end
26
+ when ??
27
+ (node.is_a?(Hash) ? node.keys : (0..node.size)).each do |e|
28
+ subenum = ::JsonPath.new(sub_path[2, sub_path.size - 3]).on(node[e])
29
+ each(node[e], pos + 1, &blk) if subenum.any?{|n| true}
30
+ end
31
+ else
32
+ if node.is_a?(Array)
33
+ @obj = node
34
+ array_args = sub_path.gsub('@','@obj').split(':')
35
+ start_idx = process_function_or_literal(array_args[0], 0)
36
+ next unless start_idx
37
+ start_idx %= node.size
38
+ end_idx = (array_args[1] && process_function_or_literal(array_args[1], -1) || (sub_path.count(':') == 0 ? start_idx : -1))
39
+ next unless end_idx
40
+ end_idx %= node.size
41
+ step = process_function_or_literal(array_args[2], 1)
42
+ next unless step
43
+ (start_idx..end_idx).step(step) {|i| each(node[i], pos + 1, &blk)}
42
44
  end
43
45
  end
44
- else
45
- blk.call(node) if pos == (@path.size - 1) && node && eval("node #{@path[pos]}")
46
46
  end
47
+ else
48
+ blk.call(node) if pos == (@path.size - 1) && node && allow_eval? && eval("node #{@path[pos]}")
49
+ end
47
50
 
48
- if pos > 0 && @path[pos-1] == '..'
49
- case node
50
- when Hash
51
- node.values.each {|n| each(n, pos, &blk) }
52
- when Array
53
- node.each {|n| each(n, pos, &blk) }
54
- end
51
+ if pos > 0 && @path[pos-1] == '..'
52
+ case node
53
+ when Hash
54
+ node.values.each {|n| each(n, pos, &blk) }
55
+ when Array
56
+ node.each {|n| each(n, pos, &blk) }
55
57
  end
56
58
  end
57
59
  end
60
+
61
+ private
62
+ def process_function_or_literal(exp, default)
63
+ if exp.nil?
64
+ default
65
+ elsif exp[0] == ?(
66
+ allow_eval? ? eval(exp) : nil
67
+ elsif exp.empty?
68
+ default
69
+ else
70
+ Integer(exp)
71
+ end
72
+ end
73
+
74
+ def allow_eval?
75
+ @options.nil? || @options[:allow_eval] != false
76
+ end
58
77
  end
59
78
  end
@@ -1,3 +1,3 @@
1
1
  class JsonPath
2
- VERSION = '0.3.2'
2
+ VERSION = '0.3.3'
3
3
  end
@@ -29,8 +29,8 @@ class TestJsonpath < MiniTest::Unit::TestCase
29
29
  "bicycle"=> {
30
30
  "color"=> "red",
31
31
  "price"=> 19.95,
32
- "catalogue_number" => 12345,
33
- } } }
32
+ "catalogue_number" => 12345 }
33
+ } }
34
34
  end
35
35
 
36
36
  def test_lookup_direct_path
@@ -72,6 +72,11 @@ class TestJsonpath < MiniTest::Unit::TestCase
72
72
  def test_recognize_filters
73
73
  assert_equal [@object['store']['book'][2], @object['store']['book'][3]], JsonPath.new("$..book[?(@['isbn'])]").on(@object)
74
74
  assert_equal [@object['store']['book'][0], @object['store']['book'][2]], JsonPath.new("$..book[?(@['price'] < 10)]").on(@object)
75
+ assert_equal [@object['store']['book'][2], @object['store']['book'][3]], JsonPath.new("$..book[?(@.isbn)]").on(@object)
76
+ end
77
+
78
+ def test_no_eval
79
+ assert_equal [], JsonPath.new('$..book[(@.length-2)]', :allow_eval => false).on(@object)
75
80
  end
76
81
 
77
82
  def test_paths_with_underscores
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonpath
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 2
10
- version: 0.3.2
9
+ - 3
10
+ version: 0.3.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Joshua Hull
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-07 00:00:00 -07:00
18
+ date: 2011-06-08 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency