jsonpath 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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