jsonpath 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +4 -4
- data/Rakefile +9 -1
- data/VERSION +1 -1
- data/jsonpath.gemspec +51 -0
- data/lib/jsonpath.rb +28 -19
- data/lib/jsonpath/{expression.rb → enumerable.rb} +10 -47
- data/spec/jsonpath_spec.rb +54 -52
- data/test/reference_test.rb +134 -0
- data/test/test_helper.rb +22 -0
- metadata +16 -7
- data/lib/jsonpath/wrapper.rb +0 -14
data/README.rdoc
CHANGED
@@ -4,7 +4,7 @@ This is an implementation of http://goessner.net/articles/JsonPath/.
|
|
4
4
|
|
5
5
|
== Usage
|
6
6
|
|
7
|
-
|
7
|
+
object = JSON.parse(<<-HERE_DOC))
|
8
8
|
{"store":
|
9
9
|
{"bicycle":
|
10
10
|
{"price":19.95, "color":"red"},
|
@@ -18,11 +18,11 @@ This is an implementation of http://goessner.net/articles/JsonPath/.
|
|
18
18
|
}
|
19
19
|
HERE_DOC
|
20
20
|
|
21
|
-
|
21
|
+
JsonPath.new('$..price').on(object).to_a
|
22
22
|
=> [19.95, 8.95, 12.99, 8.99, 22.99]
|
23
23
|
|
24
|
-
|
24
|
+
JsonPath.new('$..author').on(object).to_a
|
25
25
|
=> ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"]
|
26
26
|
|
27
|
-
|
27
|
+
JsonPath.new('$..book[::2]').on(object).to_a
|
28
28
|
=> [{"price"=>8.95, "category"=>"reference", "author"=>"Nigel Rees", "title"=>"Sayings of the Century"}, {"price"=>8.99, "category"=>"fiction", "author"=>"Herman Melville", "title"=>"Moby Dick", "isbn"=>"0-553-21311-3"}]
|
data/Rakefile
CHANGED
@@ -8,7 +8,7 @@ begin
|
|
8
8
|
s.email = "joshbuddy@gmail.com"
|
9
9
|
s.homepage = "http://github.com/joshbuddy/jsonpath"
|
10
10
|
s.authors = ['Joshua Hull']
|
11
|
-
s.files =
|
11
|
+
s.files = `git ls-files`.split(/\n/)
|
12
12
|
end
|
13
13
|
Jeweler::GemcutterTasks.new
|
14
14
|
rescue LoadError
|
@@ -28,7 +28,15 @@ require 'spec'
|
|
28
28
|
require 'spec/rake/spectask'
|
29
29
|
|
30
30
|
Spec::Rake::SpecTask.new do |t|
|
31
|
+
t.ruby_opts = ['-rubygems']
|
31
32
|
t.spec_opts ||= []
|
32
33
|
t.spec_opts << "--options" << "spec/spec.opts"
|
33
34
|
t.spec_files = FileList['spec/*.rb']
|
34
35
|
end
|
36
|
+
|
37
|
+
#require 'rake/testtask'
|
38
|
+
#Rake::TestTask.new(:test) do |test|
|
39
|
+
# test.libs << 'lib' << 'test'
|
40
|
+
# test.pattern = 'test/**/*_test.rb'
|
41
|
+
# test.verbose = true
|
42
|
+
#end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/jsonpath.gemspec
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{jsonpath}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Joshua Hull"]
|
12
|
+
s.date = %q{2010-03-27}
|
13
|
+
s.description = %q{Ruby implementation of http://goessner.net/articles/JsonPath/}
|
14
|
+
s.email = %q{joshbuddy@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
"README.rdoc",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION",
|
22
|
+
"jsonpath.gemspec",
|
23
|
+
"lib/jsonpath.rb",
|
24
|
+
"lib/jsonpath/enumerable.rb",
|
25
|
+
"spec/jsonpath_spec.rb",
|
26
|
+
"spec/spec.opts",
|
27
|
+
"spec/spec_helper.rb"
|
28
|
+
]
|
29
|
+
s.homepage = %q{http://github.com/joshbuddy/jsonpath}
|
30
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
31
|
+
s.require_paths = ["lib"]
|
32
|
+
s.rubygems_version = %q{1.3.6}
|
33
|
+
s.summary = %q{Ruby implementation of http://goessner.net/articles/JsonPath/}
|
34
|
+
s.test_files = [
|
35
|
+
"spec/jsonpath_spec.rb",
|
36
|
+
"spec/spec_helper.rb",
|
37
|
+
"test/reference_test.rb",
|
38
|
+
"test/test_helper.rb"
|
39
|
+
]
|
40
|
+
|
41
|
+
if s.respond_to? :specification_version then
|
42
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
43
|
+
s.specification_version = 3
|
44
|
+
|
45
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
46
|
+
else
|
47
|
+
end
|
48
|
+
else
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
data/lib/jsonpath.rb
CHANGED
@@ -1,25 +1,34 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
|
1
|
+
require 'strscan'
|
2
|
+
require 'load_path_find'
|
3
|
+
|
4
|
+
$LOAD_PATH.add_current
|
5
|
+
|
6
|
+
require File.join('jsonpath', 'enumerable')
|
4
7
|
|
5
8
|
class JsonPath
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
|
10
|
+
attr_reader :path
|
11
|
+
|
12
|
+
def initialize(path)
|
13
|
+
scanner = StringScanner.new(path)
|
14
|
+
@path = []
|
15
|
+
bracket_count = 0
|
16
|
+
while not scanner.eos?
|
17
|
+
token = scanner.scan_until(/($|\$|@|[a-zA-Z]+|\[.*?\]|\.\.|\.(?!\.))/)
|
18
|
+
case token
|
19
|
+
when '.'
|
20
|
+
# do nothing
|
21
|
+
when /^[a-zA-Z]+$/
|
22
|
+
@path << "['#{token}']"
|
23
|
+
else
|
24
|
+
bracket_count == 0 && @path << token or @path[-1] += token
|
25
|
+
bracket_count += token.count('[') - token.count(']')
|
26
|
+
end
|
13
27
|
end
|
14
28
|
end
|
15
|
-
|
16
|
-
def
|
17
|
-
|
18
|
-
if block_given?
|
19
|
-
yield @wrapper
|
20
|
-
else
|
21
|
-
@wrapper
|
22
|
-
end
|
29
|
+
|
30
|
+
def on(object)
|
31
|
+
JsonPath::Enumerable.new(self, object)
|
23
32
|
end
|
24
|
-
|
33
|
+
|
25
34
|
end
|
@@ -1,44 +1,12 @@
|
|
1
|
-
require 'strscan'
|
2
|
-
|
3
1
|
class JsonPath
|
4
|
-
class
|
5
|
-
|
6
|
-
scanner = StringScanner.new(expression)
|
7
|
-
@path = []
|
8
|
-
bracket_count = 0
|
9
|
-
while not scanner.eos?
|
10
|
-
token = scanner.scan_until(/($|\$|@|[a-zA-Z]+|\[.*?\]|\.\.|\.(?!\.))/)
|
11
|
-
case token
|
12
|
-
when '.'
|
13
|
-
# do nothing
|
14
|
-
when /^[a-zA-Z]+$/
|
15
|
-
@path << "['#{token}']"
|
16
|
-
else
|
17
|
-
bracket_count == 0 && @path << token or @path[-1] += token
|
18
|
-
bracket_count += token.count('[') - token.count(']')
|
19
|
-
end
|
20
|
-
end
|
21
|
-
@object = object
|
22
|
-
end
|
2
|
+
class Enumerable
|
3
|
+
include ::Enumerable
|
23
4
|
|
24
|
-
def
|
25
|
-
|
26
|
-
false
|
5
|
+
def initialize(path, object)
|
6
|
+
@path, @object = path.path, object
|
27
7
|
end
|
28
8
|
|
29
|
-
def
|
30
|
-
store = []
|
31
|
-
each(node) {|o| store << o}
|
32
|
-
store
|
33
|
-
end
|
34
|
-
|
35
|
-
def map(node = @object)
|
36
|
-
store = []
|
37
|
-
each(node) {|o| store << (yield o)}
|
38
|
-
store
|
39
|
-
end
|
40
|
-
|
41
|
-
def each(node = @object, pos = 0, options = {}, &blk)
|
9
|
+
def each(node = @object, pos = 0, &blk)
|
42
10
|
if pos == @path.size
|
43
11
|
return blk.call(node)
|
44
12
|
else
|
@@ -59,14 +27,8 @@ class JsonPath
|
|
59
27
|
end
|
60
28
|
when ??
|
61
29
|
(node.is_a?(Hash) ? node.keys : (0..node.size)).each do |e|
|
62
|
-
::JsonPath.
|
63
|
-
|
64
|
-
begin
|
65
|
-
each(node[e], pos + 1, &blk) if jp.test?(node[e])
|
66
|
-
rescue
|
67
|
-
# ignore ..
|
68
|
-
end
|
69
|
-
end
|
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}
|
70
32
|
end
|
71
33
|
else
|
72
34
|
if node.is_a?(Array)
|
@@ -82,7 +44,7 @@ class JsonPath
|
|
82
44
|
else
|
83
45
|
blk.call(node) if pos == (@path.size - 1) && eval("node #{@path[pos]}")
|
84
46
|
end
|
85
|
-
|
47
|
+
|
86
48
|
if pos > 0 && @path[pos-1] == '..'
|
87
49
|
case node
|
88
50
|
when Hash
|
@@ -94,4 +56,5 @@ class JsonPath
|
|
94
56
|
end
|
95
57
|
end
|
96
58
|
end
|
97
|
-
end
|
59
|
+
end
|
60
|
+
|
data/spec/jsonpath_spec.rb
CHANGED
@@ -2,86 +2,88 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe "JsonPath" do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
"
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
"
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
"
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
"
|
25
|
-
|
26
|
-
|
27
|
-
|
5
|
+
before(:each) do
|
6
|
+
@object = { "store"=> {
|
7
|
+
"book" => [
|
8
|
+
{ "category"=> "reference",
|
9
|
+
"author"=> "Nigel Rees",
|
10
|
+
"title"=> "Sayings of the Century",
|
11
|
+
"price"=> 8.95
|
12
|
+
},
|
13
|
+
{ "category"=> "fiction",
|
14
|
+
"author"=> "Evelyn Waugh",
|
15
|
+
"title"=> "Sword of Honour",
|
16
|
+
"price"=> 12.99
|
17
|
+
},
|
18
|
+
{ "category"=> "fiction",
|
19
|
+
"author"=> "Herman Melville",
|
20
|
+
"title"=> "Moby Dick",
|
21
|
+
"isbn"=> "0-553-21311-3",
|
22
|
+
"price"=> 8.99
|
23
|
+
},
|
24
|
+
{ "category"=> "fiction",
|
25
|
+
"author"=> "J. R. R. Tolkien",
|
26
|
+
"title"=> "The Lord of the Rings",
|
27
|
+
"isbn"=> "0-395-19395-8",
|
28
|
+
"price"=> 22.99
|
29
|
+
}
|
30
|
+
],
|
31
|
+
"bicycle"=> {
|
32
|
+
"color"=> "red",
|
33
|
+
"price"=> 19.95
|
28
34
|
}
|
29
|
-
],
|
30
|
-
"bicycle"=> {
|
31
|
-
"color"=> "red",
|
32
|
-
"price"=> 19.95
|
33
35
|
}
|
34
36
|
}
|
35
|
-
|
36
|
-
json = JsonPath.wrap(object)
|
37
|
+
end
|
38
|
+
#json = JsonPath.wrap(object)
|
37
39
|
|
38
40
|
it "should lookup a direct path" do
|
39
|
-
|
41
|
+
JsonPath.new('$.store.*').on(@object).to_a.first['book'].size.should == 4
|
40
42
|
end
|
41
43
|
|
42
44
|
it "should retrieve all authors" do
|
43
|
-
|
44
|
-
object['store']['book'][0]['author'],
|
45
|
-
object['store']['book'][1]['author'],
|
46
|
-
object['store']['book'][2]['author'],
|
47
|
-
object['store']['book'][3]['author']
|
45
|
+
JsonPath.new('$..author').on(@object).to_a.should == [
|
46
|
+
@object['store']['book'][0]['author'],
|
47
|
+
@object['store']['book'][1]['author'],
|
48
|
+
@object['store']['book'][2]['author'],
|
49
|
+
@object['store']['book'][3]['author']
|
48
50
|
]
|
49
51
|
end
|
50
52
|
|
51
53
|
it "should retrieve all prices" do
|
52
|
-
|
53
|
-
object['store']['bicycle']['price'],
|
54
|
-
object['store']['book'][0]['price'],
|
55
|
-
object['store']['book'][1]['price'],
|
56
|
-
object['store']['book'][2]['price'],
|
57
|
-
object['store']['book'][3]['price']
|
54
|
+
JsonPath.new('$..price').on(@object).to_a.should == [
|
55
|
+
@object['store']['bicycle']['price'],
|
56
|
+
@object['store']['book'][0]['price'],
|
57
|
+
@object['store']['book'][1]['price'],
|
58
|
+
@object['store']['book'][2]['price'],
|
59
|
+
@object['store']['book'][3]['price']
|
58
60
|
]
|
59
61
|
end
|
60
62
|
|
61
63
|
it "should recognize all types of array splices" do
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
64
|
+
JsonPath.new('$..book[0:1:1]').on(@object).to_a.should == [@object['store']['book'][0], @object['store']['book'][1]]
|
65
|
+
JsonPath.new('$..book[1::2]').on(@object).to_a.should == [@object['store']['book'][1], @object['store']['book'][3]]
|
66
|
+
JsonPath.new('$..book[::2]').on(@object).to_a.should == [@object['store']['book'][0], @object['store']['book'][2]]
|
67
|
+
JsonPath.new('$..book[:-2:2]').on(@object).to_a.should == [@object['store']['book'][0], @object['store']['book'][2]]
|
68
|
+
JsonPath.new('$..book[2::]').on(@object).to_a.should == [@object['store']['book'][2], @object['store']['book'][3]]
|
67
69
|
end
|
68
70
|
|
69
71
|
it "should recognize array comma syntax" do
|
70
|
-
|
71
|
-
|
72
|
+
JsonPath.new('$..book[0,1]').on(@object).to_a.should == [@object['store']['book'][0], @object['store']['book'][1]]
|
73
|
+
JsonPath.new('$..book[2,-1::]').on(@object).to_a.should == [@object['store']['book'][2], @object['store']['book'][3]]
|
72
74
|
end
|
73
75
|
|
74
76
|
it "should support filters" do
|
75
|
-
|
76
|
-
|
77
|
+
JsonPath.new("$..book[?(@['isbn'])]").on(@object).to_a.should == [@object['store']['book'][2], @object['store']['book'][3]]
|
78
|
+
JsonPath.new("$..book[?(@['price'] < 10)]").on(@object).to_a.should == [@object['store']['book'][0], @object['store']['book'][2]]
|
77
79
|
end
|
78
80
|
|
79
81
|
it "should support eval'd array indicies" do
|
80
|
-
|
82
|
+
JsonPath.new('$..book[(@.length-2)]').on(@object).to_a.should == [@object['store']['book'][2]]
|
81
83
|
end
|
82
84
|
|
83
85
|
it "should correct retrieve the right number of all nodes" do
|
84
|
-
|
86
|
+
JsonPath.new('$..*').on(@object).to_a.size.should == 28
|
85
87
|
end
|
86
88
|
|
87
89
|
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require File.dirname(__FILE__) << "/test_helper"
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class ReferenceTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
context 'Sample 1' do
|
7
|
+
setup { @json = %({"a":"a","b":"b","c d":"e"}) }
|
8
|
+
#should 'resolve a simple path' do
|
9
|
+
# assert_resolves(object, "$.a", ["a"])
|
10
|
+
#end
|
11
|
+
#should 'resolve a path with quotes in brackets' do
|
12
|
+
# assert_resolves(object, "$['a']", ["a"])
|
13
|
+
#end
|
14
|
+
should 'resolve a path with a space' do
|
15
|
+
assert_resolves(object, "$.'c d'", ["e"])
|
16
|
+
end
|
17
|
+
#should 'resolve a star' do
|
18
|
+
# assert_resolves(object, "$.*", ["a", "b", "e"])
|
19
|
+
#end
|
20
|
+
#should 'resolve a star with quotes in brackets' do
|
21
|
+
# assert_resolves(object, "$['*']", ["a", "b", "e"])
|
22
|
+
#end
|
23
|
+
#should 'resolve a star with quotes' do
|
24
|
+
# assert_resolves(object, "$[*]", ["a", "b", "e"])
|
25
|
+
#end
|
26
|
+
end
|
27
|
+
#context 'Sample 2' do
|
28
|
+
# setup { @json = %([1, "2", 3.14, true, null]) }
|
29
|
+
# should 'resolve with a number in brackets' do
|
30
|
+
# assert_resolves(object, "$[0]", [1])
|
31
|
+
# end
|
32
|
+
# should 'resolve another number in brackets' do
|
33
|
+
# assert_resolves(object, "$[4]", [nil])
|
34
|
+
# end
|
35
|
+
# should 'resolve a star in brackets' do
|
36
|
+
# assert_resolves(object, "$[*]", [1, "2", 3.14, true, nil])
|
37
|
+
# end
|
38
|
+
# should 'resolve an end slice' do
|
39
|
+
# assert_resolves(object, "$[-1:]", [nil])
|
40
|
+
# end
|
41
|
+
#end
|
42
|
+
#context 'Sample 3' do
|
43
|
+
# setup { @json = %({"points":[{"id": "i1", "x": 4, "y": -5}, {"id": "i2", "x": -2, "y": 2, "z": 1}, {"id": "i3", "x": 8, "y": 3}, {"id": "i4", "x": -6, "y": -1}, {"id": "i5", "x": 0, "y": 2, "z": 1}, {"id": "i6", "x": 1, "y": 4}]}) }
|
44
|
+
# should 'resolve correctly' do
|
45
|
+
# assert_resolves(object, "$.points[1]", [{"id" => "i2", "x" => -2, "y" => 2, "z" => 1}])
|
46
|
+
# end
|
47
|
+
# should 'resolve a chained path' do
|
48
|
+
# assert_resolves(object, "$.points[4].x", [0])
|
49
|
+
# end
|
50
|
+
# should 'resolve by attribute match' do
|
51
|
+
# assert_resolves(object, "$.points[?(@['id']=='i4')].x", [-6])
|
52
|
+
# end
|
53
|
+
# should 'resolve a chained path with a star in brackets' do
|
54
|
+
# assert_resolves(object, "$.points[*].x", [4, -2, 8, -6, 0, 1])
|
55
|
+
# end
|
56
|
+
# should 'resolve by attribute operation' do
|
57
|
+
# assert_resolves(object, "$['points'][?(@['x']*@['x']+@['y']*@['y'] > 50)].id", ["i3"])
|
58
|
+
# end
|
59
|
+
# should 'resolve by attribute existence' do
|
60
|
+
# assert_resolves(object, "$.points[?(@['z'])].id", ["i2", "i5"])
|
61
|
+
# end
|
62
|
+
# should 'resolve by length property operation' do
|
63
|
+
# assert_resolves(object, "$.points[(@.length-1)].id", ["i6"])
|
64
|
+
# end
|
65
|
+
#end
|
66
|
+
#context 'Sample 4' do
|
67
|
+
# setup { @json = %({"menu":{"header":"SVG Viewer","items":[{"id": "Open"}, {"id": "OpenNew", "label": "Open New"}, null, {"id": "ZoomIn", "label": "Zoom In"}, {"id": "ZoomOut", "label": "Zoom Out"}, {"id": "OriginalView", "label": "Original View"}, null, {"id": "Quality"}, {"id": "Pause"}, {"id": "Mute"}, null, {"id": "Find", "label": "Find..."}, {"id": "FindAgain", "label": "Find Again"}, {"id": "Copy"}, {"id": "CopyAgain", "label": "Copy Again"}, {"id": "CopySVG", "label": "Copy SVG"}, {"id": "ViewSVG", "label": "View SVG"}, {"id": "ViewSource", "label": "View Source"}, {"id": "SaveAs", "label": "Save As"}, null, {"id": "Help"}, {"id": "About", "label": "About Adobe CVG Viewer..."}]}}) }
|
68
|
+
# should 'resolve testing on attribute' do
|
69
|
+
# assert_resolves(object, "$.menu.items[?(@ && @['id'] && !@['label'])].id", ["Open", "Quality", "Pause", "Mute", "Copy", "Help"])
|
70
|
+
# end
|
71
|
+
# should 'resolve testing on attribute with regular expression' do
|
72
|
+
# assert_resolves(object, "$.menu.items[?(@ && @['label'] && @['label'] =~ /SVG/)].id", ["CopySVG", "ViewSVG"])
|
73
|
+
# end
|
74
|
+
# should 'resolve on negative' do
|
75
|
+
# # !nil == true in Ruby
|
76
|
+
# assert_resolves(object, "$.menu.items[?(!@)]", [nil, nil, nil, nil])
|
77
|
+
# end
|
78
|
+
# should 'resolve descendant with number in brackets' do
|
79
|
+
# assert_resolves(object, "$..[0]", [{"id" => "Open"}])
|
80
|
+
# end
|
81
|
+
#end
|
82
|
+
#context 'Sample 5' do
|
83
|
+
# setup { @json = %({"a":[1, 2, 3, 4],"b":[5, 6, 7, 8]}) }
|
84
|
+
# should 'resolve descendant with number in brackets' do
|
85
|
+
# assert_resolves(object, "$..[0]", [1, 5])
|
86
|
+
# end
|
87
|
+
# should 'resolve descendant last items' do
|
88
|
+
# assert_resolves(object, "$..[-1:]", [4, 8])
|
89
|
+
# end
|
90
|
+
# should 'resolve by descendant value' do
|
91
|
+
# assert_resolves(object, "$..[?(@.is_a?(Numeric) && @ % 2 == 0)]", [2, 4, 6, 8])
|
92
|
+
# end
|
93
|
+
#end
|
94
|
+
#context 'Sample 6' do
|
95
|
+
# setup { @json = %({"lin":{"color":"red","x":2,"y":3},"cir":{"color":"blue","x":5,"y":2,"r":1},"arc":{"color":"green","x":2,"y":4,"r":2,"phi0":30,"dphi":120},"pnt":{"x":0,"y":7}}) }
|
96
|
+
# should 'resolve by operation in quotes' do
|
97
|
+
# assert_resolves(object, "$.'?(@['color'])'.x", [2, 5, 2])
|
98
|
+
# end
|
99
|
+
# should 'resolve by multiple quoted values in brackets' do
|
100
|
+
# assert_resolves(object, "$['lin','cir'].color", ["red", "blue"])
|
101
|
+
# end
|
102
|
+
#end
|
103
|
+
#context 'Sample 7' do
|
104
|
+
# setup { @json = %({"text":["hello", "world2.0"]}) }
|
105
|
+
# should 'resolve correctly filter 1' do
|
106
|
+
# assert_resolves(object, "$.text[?(@.length > 5)]", ["world2.0"])
|
107
|
+
# end
|
108
|
+
# should 'resolve correctly filter 2' do
|
109
|
+
# assert_resolves(object, "$.text[?(@[0, 1] == 'h')]", ["hello"])
|
110
|
+
# end
|
111
|
+
#end
|
112
|
+
#context 'Sample 8' do
|
113
|
+
# setup { @json = %({"a":{"a":2,"b":3},"b":{"a":4,"b":5},"c":{"a":{"a":6,"b":7},"c":8}}) }
|
114
|
+
# should 'resolve descendant' do
|
115
|
+
# assert_resolves(object, "$..a", [{"a" => 2, "b" => 3}, 2, 4, {"a" => 6, "b" => 7}, 6])
|
116
|
+
# end
|
117
|
+
#end
|
118
|
+
#context 'Sample 10' do
|
119
|
+
# setup { @json = %({"a":[{"a": 5, "@": 2, "$": 3}, {"a": 6, "@": 3, "$": 4}, {"a": 7, "@": 4, "$": 5}]}) }
|
120
|
+
# should 'resolve with quoted operation and escaped special character' do
|
121
|
+
# assert_resolves(object, "$.a[?(@['\\@']==3)]", [{"a" => 6, "@" => 3, "$" => 4}])
|
122
|
+
# end
|
123
|
+
# should 'resolve with quotes and brackets in operation' do
|
124
|
+
# assert_resolves(object, "$.a[?(@['$']==5)]", [{"a" => 7, "@" => 4, "$" => 5}])
|
125
|
+
# end
|
126
|
+
#end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def object
|
131
|
+
JSON.parse(@json)
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
+
require 'jsonpath'
|
8
|
+
|
9
|
+
class Test::Unit::TestCase
|
10
|
+
|
11
|
+
private
|
12
|
+
def assert_resolves(obj, path, result)
|
13
|
+
assert_equal safe_sort(result), safe_sort(JsonPath.new(path).on(obj).to_a)
|
14
|
+
end
|
15
|
+
|
16
|
+
def safe_sort(objs)
|
17
|
+
objs.sort_by do |obj|
|
18
|
+
obj ? obj.to_s : 0.to_s
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonpath
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Joshua Hull
|
@@ -9,7 +14,7 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-03-27 00:00:00 -04:00
|
13
18
|
default_executable:
|
14
19
|
dependencies: []
|
15
20
|
|
@@ -25,9 +30,9 @@ files:
|
|
25
30
|
- README.rdoc
|
26
31
|
- Rakefile
|
27
32
|
- VERSION
|
33
|
+
- jsonpath.gemspec
|
28
34
|
- lib/jsonpath.rb
|
29
|
-
- lib/jsonpath/
|
30
|
-
- lib/jsonpath/wrapper.rb
|
35
|
+
- lib/jsonpath/enumerable.rb
|
31
36
|
- spec/jsonpath_spec.rb
|
32
37
|
- spec/spec.opts
|
33
38
|
- spec/spec_helper.rb
|
@@ -44,21 +49,25 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
44
49
|
requirements:
|
45
50
|
- - ">="
|
46
51
|
- !ruby/object:Gem::Version
|
52
|
+
segments:
|
53
|
+
- 0
|
47
54
|
version: "0"
|
48
|
-
version:
|
49
55
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
56
|
requirements:
|
51
57
|
- - ">="
|
52
58
|
- !ruby/object:Gem::Version
|
59
|
+
segments:
|
60
|
+
- 0
|
53
61
|
version: "0"
|
54
|
-
version:
|
55
62
|
requirements: []
|
56
63
|
|
57
64
|
rubyforge_project:
|
58
|
-
rubygems_version: 1.3.
|
65
|
+
rubygems_version: 1.3.6
|
59
66
|
signing_key:
|
60
67
|
specification_version: 3
|
61
68
|
summary: Ruby implementation of http://goessner.net/articles/JsonPath/
|
62
69
|
test_files:
|
63
70
|
- spec/jsonpath_spec.rb
|
64
71
|
- spec/spec_helper.rb
|
72
|
+
- test/reference_test.rb
|
73
|
+
- test/test_helper.rb
|