jsonpath 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,37 @@
1
+ # Jsonpath
2
+
3
+ This is an implementation of http://goessner.net/articles/JsonPath/.
4
+
5
+ ## Usage
6
+
7
+ There is stand-alone usage through the binary `jsonpath`
8
+
9
+ jsonpath [expression] (file|string)
10
+
11
+ If you omit the second argument, it will read stdin, assuming one valid JSON object
12
+ per line. Expression must be a valid jsonpath expression.
13
+
14
+ As well, you can include it as a library.
15
+
16
+ object = JSON.parse(<<-HERE_DOC))
17
+ {"store":
18
+ {"bicycle":
19
+ {"price":19.95, "color":"red"},
20
+ "book":[
21
+ {"price":8.95, "category":"reference", "title":"Sayings of the Century", "author":"Nigel Rees"},
22
+ {"price":12.99, "category":"fiction", "title":"Sword of Honour", "author":"Evelyn Waugh"},
23
+ {"price":8.99, "category":"fiction", "isbn":"0-553-21311-3", "title":"Moby Dick", "author":"Herman Melville"},
24
+ {"price":22.99, "category":"fiction", "isbn":"0-395-19395-8", "title":"The Lord of the Rings", "author":"J. R. R. Tolkien"}
25
+ ]
26
+ }
27
+ }
28
+ HERE_DOC
29
+
30
+ JsonPath.new('$..price').on(object).to_a
31
+ # => [19.95, 8.95, 12.99, 8.99, 22.99]
32
+
33
+ JsonPath.new('$..author').on(object).to_a
34
+ # => ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"]
35
+
36
+ JsonPath.new('$..book[::2]').on(object).to_a
37
+ # => [{"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
@@ -1,25 +1,5 @@
1
- require 'rake/testtask'
2
-
3
- #desc "Build it up"
4
- #task :build do
5
- # sh "rex --independent -o lib/jsonpath/grammar.rex.rb lib/grammar/grammar.rex"
6
- # sh "racc -v -O parser.output -o lib/jsonpath/grammar.y.rb lib/grammar/grammar.y"
7
- #end
8
-
9
- begin
10
- require 'jeweler'
11
- Jeweler::Tasks.new do |s|
12
- s.name = "jsonpath"
13
- s.description = s.summary = "Ruby implementation of http://goessner.net/articles/JsonPath/"
14
- s.email = "joshbuddy@gmail.com"
15
- s.homepage = "http://github.com/joshbuddy/jsonpath"
16
- s.authors = ['Joshua Hull']
17
- s.files = `git ls-files`.split(/\n/)
18
- end
19
- Jeweler::GemcutterTasks.new
20
- rescue LoadError
21
- puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
22
- end
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
23
3
 
24
4
  require 'rake/rdoctask'
25
5
  desc "Generate documentation"
@@ -39,10 +19,3 @@ Spec::Rake::SpecTask.new do |t|
39
19
  t.spec_opts << "--options" << "spec/spec.opts"
40
20
  t.spec_files = FileList['spec/*.rb']
41
21
  end
42
-
43
- require 'rake/testtask'
44
- Rake::TestTask.new(:test) do |test|
45
- test.libs << 'lib' << 'test'
46
- test.pattern = 'test/**/*_test.rb'
47
- test.verbose = true
48
- end
@@ -0,0 +1,24 @@
1
+ #!/usr/local/env ruby
2
+
3
+ require 'jsonpath'
4
+ require 'json'
5
+
6
+ def usage
7
+ puts "jsonpath [expression] (file|string)
8
+
9
+ If you omit the second argument, it will read stdin, assuming one valid JSON object
10
+ per line. Expression must be a valid jsonpath expression."
11
+ exit!
12
+ end
13
+
14
+ usage unless ARGV[0]
15
+
16
+ jsonpath = JsonPath.new(ARGV[0])
17
+ case ARGV[1]
18
+ when nil #stdin
19
+ until STDIN.eof?
20
+ puts jsonpath.on(JSON.parse(STDIN.readline)).to_a.to_json
21
+ end
22
+ when String
23
+ puts jsonpath.on(JSON.parse(File.exist?(ARGV[1]) ? File.read(ARGV[1]) : ARGV[1])).to_a.to_json
24
+ end
@@ -1,48 +1,36 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
1
  # -*- encoding: utf-8 -*-
5
2
 
6
- Gem::Specification.new do |s|
7
- s.name = %q{jsonpath}
8
- s.version = "0.1.2"
3
+ require File.join(File.dirname(__FILE__), 'lib', 'jsonpath', 'version')
9
4
 
5
+ Gem::Specification.new do |s|
6
+ s.name = 'jsonpath'
7
+ s.version = JsonPath::VERSION
10
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
9
  s.authors = ["Joshua Hull"]
12
- s.date = %q{2010-04-27}
13
- s.description = %q{Ruby implementation of http://goessner.net/articles/JsonPath/}
10
+ s.summary = "Ruby implementation of http://goessner.net/articles/JsonPath/"
11
+ s.description = "Ruby implementation of http://goessner.net/articles/JsonPath/."
14
12
  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
- ]
13
+ s.extra_rdoc_files = ['README.md']
14
+ s.files = `git ls-files`.split("\n")
29
15
  s.homepage = %q{http://github.com/joshbuddy/jsonpath}
30
16
  s.rdoc_options = ["--charset=UTF-8"]
31
17
  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
- ]
18
+ s.rubygems_version = %q{1.3.7}
19
+ s.test_files = `git ls-files`.split("\n").select{|f| f =~ /^spec/}
20
+ s.rubyforge_project = 'jsonpath'
21
+
22
+ # dependencies
23
+ s.add_runtime_dependency 'json'
24
+ s.add_development_dependency 'code_stats'
25
+ s.add_development_dependency 'rake'
26
+ s.add_development_dependency 'rspec', '< 2.0.0'
27
+ s.add_development_dependency 'bundler', '~> 1.0.0'
40
28
 
41
29
  if s.respond_to? :specification_version then
42
30
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
43
31
  s.specification_version = 3
44
32
 
45
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
33
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
34
  else
47
35
  end
48
36
  else
@@ -1,7 +1,6 @@
1
1
  require 'strscan'
2
- $LOAD_PATH << File.expand_path(File.basename(__FILE__))
3
-
4
2
  require File.join('jsonpath', 'enumerable')
3
+ require File.join('jsonpath', 'version')
5
4
 
6
5
  class JsonPath
7
6
 
@@ -0,0 +1,3 @@
1
+ class JsonPath
2
+ VERSION = '0.2.0'
3
+ end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonpath
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 23
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
- - 1
8
8
  - 2
9
- version: 0.1.2
9
+ - 0
10
+ version: 0.2.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - Joshua Hull
@@ -14,25 +15,100 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-04-27 00:00:00 -04:00
18
+ date: 2011-03-17 00:00:00 -07:00
18
19
  default_executable:
19
- dependencies: []
20
-
21
- description: Ruby implementation of http://goessner.net/articles/JsonPath/
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: json
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: code_stats
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: rake
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: rspec
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - <
70
+ - !ruby/object:Gem::Version
71
+ hash: 15
72
+ segments:
73
+ - 2
74
+ - 0
75
+ - 0
76
+ version: 2.0.0
77
+ type: :development
78
+ version_requirements: *id004
79
+ - !ruby/object:Gem::Dependency
80
+ name: bundler
81
+ prerelease: false
82
+ requirement: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ hash: 23
88
+ segments:
89
+ - 1
90
+ - 0
91
+ - 0
92
+ version: 1.0.0
93
+ type: :development
94
+ version_requirements: *id005
95
+ description: Ruby implementation of http://goessner.net/articles/JsonPath/.
22
96
  email: joshbuddy@gmail.com
23
97
  executables: []
24
98
 
25
99
  extensions: []
26
100
 
27
101
  extra_rdoc_files:
28
- - README.rdoc
102
+ - README.md
29
103
  files:
30
- - README.rdoc
104
+ - README.md
31
105
  - Rakefile
32
106
  - VERSION
107
+ - bin/jsonpath
33
108
  - jsonpath.gemspec
34
109
  - lib/jsonpath.rb
35
110
  - lib/jsonpath/enumerable.rb
111
+ - lib/jsonpath/version.rb
36
112
  - spec/jsonpath_spec.rb
37
113
  - spec/spec.opts
38
114
  - spec/spec_helper.rb
@@ -46,28 +122,31 @@ rdoc_options:
46
122
  require_paths:
47
123
  - lib
48
124
  required_ruby_version: !ruby/object:Gem::Requirement
125
+ none: false
49
126
  requirements:
50
127
  - - ">="
51
128
  - !ruby/object:Gem::Version
129
+ hash: 3
52
130
  segments:
53
131
  - 0
54
132
  version: "0"
55
133
  required_rubygems_version: !ruby/object:Gem::Requirement
134
+ none: false
56
135
  requirements:
57
136
  - - ">="
58
137
  - !ruby/object:Gem::Version
138
+ hash: 3
59
139
  segments:
60
140
  - 0
61
141
  version: "0"
62
142
  requirements: []
63
143
 
64
- rubyforge_project:
65
- rubygems_version: 1.3.6
144
+ rubyforge_project: jsonpath
145
+ rubygems_version: 1.3.7
66
146
  signing_key:
67
147
  specification_version: 3
68
148
  summary: Ruby implementation of http://goessner.net/articles/JsonPath/
69
149
  test_files:
70
150
  - spec/jsonpath_spec.rb
151
+ - spec/spec.opts
71
152
  - spec/spec_helper.rb
72
- - test/reference_test.rb
73
- - test/test_helper.rb
@@ -1,28 +0,0 @@
1
- = Jsonpath
2
-
3
- This is an implementation of http://goessner.net/articles/JsonPath/.
4
-
5
- == Usage
6
-
7
- object = JSON.parse(<<-HERE_DOC))
8
- {"store":
9
- {"bicycle":
10
- {"price":19.95, "color":"red"},
11
- "book":[
12
- {"price":8.95, "category":"reference", "title":"Sayings of the Century", "author":"Nigel Rees"},
13
- {"price":12.99, "category":"fiction", "title":"Sword of Honour", "author":"Evelyn Waugh"},
14
- {"price":8.99, "category":"fiction", "isbn":"0-553-21311-3", "title":"Moby Dick", "author":"Herman Melville"},
15
- {"price":22.99, "category":"fiction", "isbn":"0-395-19395-8", "title":"The Lord of the Rings", "author":"J. R. R. Tolkien"}
16
- ]
17
- }
18
- }
19
- HERE_DOC
20
-
21
- JsonPath.new('$..price').on(object).to_a
22
- => [19.95, 8.95, 12.99, 8.99, 22.99]
23
-
24
- JsonPath.new('$..author').on(object).to_a
25
- => ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"]
26
-
27
- JsonPath.new('$..book[::2]').on(object).to_a
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"}]
@@ -1,134 +0,0 @@
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
@@ -1,22 +0,0 @@
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