jsonpath 0.1.2 → 0.2.0

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.
@@ -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