rjp 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cd9e758193d81f3ab944e5c5fd1383abbde2593d
4
+ data.tar.gz: ea16b330c441602ba7a12179d939d7d886aa8f21
5
+ SHA512:
6
+ metadata.gz: ed763647f9121b8a88948067da2493f35cb4658b2dda8942a5fa33903ac199b9e3521ab6b935a3f6044b68d2df4ead2a0ba106aaf7c6a040d3f8bd963811e65c
7
+ data.tar.gz: 2862f39b469226df41bfb5663e3340a8f8ddae24d9674429567e4204dd2e132fc6f305038e053b650d69312c75566f29a259cf81ac96f9fa488a11ee9967bd8c
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ tags
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rjp.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Tyler Dooling
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # rjp
2
+
3
+ A command line tool for formatting JSON and extracting values.
4
+
5
+ ## Installation
6
+
7
+ $ gem install rjp
8
+
9
+ ## Usage
10
+
11
+ ### Formating a JSON response
12
+ ```bash
13
+ $ curl https://api.github.com | rjp
14
+ {
15
+ "current_user_url" => "https://api.github.com/user",
16
+ "authorizations_url" => "https://api.github.com/authorizations",
17
+ "code_search_url" => "https://api.github.com/search/code?q={query}{&page,per_page,sort,order}",
18
+ "emails_url" => "https://api.github.com/user/emails",
19
+ "emojis_url" => "https://api.github.com/emojis",
20
+ "vents_url" => "https://api.github.com/events",
21
+ "feeds_url" => "https://api.github.com/feeds",
22
+ "following_url" => "https://api.github.com/user/following{/target}",
23
+ "gists_url" => "https://api.github.com/gists{/gist_id}",
24
+ "hub_url" => "https://api.github.com/hub",
25
+ "issue_search_url" => "https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}",
26
+ "issues_url" => "https://api.github.com/issues",
27
+ "keys_url" => "https://api.github.com/user/keys",
28
+ "notifications_url" => "https://api.github.com/notifications",
29
+ "organization_repositories_url" => "https://api.github.com/orgs/{org}/repos/{?type,page,per_page,sort}",
30
+ "organization_url" => "https://api.github.com/orgs/{org}",
31
+ "public_gists_url" => "https://api.github.com/gists/public",
32
+ "rate_limit_url" => "https://api.github.com/rate_limit",
33
+ "repository_url" => "https://api.github.com/repos/{owner}/{repo}",
34
+ "repository_search_url" => "https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}",
35
+ "current_user_repositories_url" => "https://api.github.com/user/repos{?type,page,per_page,sort}",
36
+ "starred_url" => "https://api.github.com/user/starred{/owner}{/repo}",
37
+ "starred_gists_url" => "https://api.github.com/gists/starred",
38
+ "team_url" => "https://api.github.com/teams",
39
+ "user_url" => "https://api.github.com/users/{user}",
40
+ "user_organizations_url" => "https://api.github.com/user/orgs",
41
+ "user_repositories_url" => "https://api.github.com/users/{user}/repos{?type,page,per_page,sort}",
42
+ "user_search_url" => "https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"
43
+ }
44
+ ```
45
+ ### Chaining to navigate hypermedia apis
46
+ ```bash
47
+ $ curl https://api.github.com | rjp -k current_user_url | xargs curl -u {github_auth} | rjp
48
+ ```
49
+ ### Default value
50
+ ```bash
51
+ $ curl https://api.github.com | rjp -k not_present -d default_value
52
+ "default_value"
53
+ ```
54
+ ### Post processing
55
+ ```bash
56
+ $ curl https://api.github.com | rjp -k current_user_url -e 'value.upscase'
57
+ "HTTPS://API.GITHUB.COM/USER"
58
+ ```
59
+
60
+ ## Contributing
61
+
62
+ 1. Fork it
63
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
64
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
65
+ 4. Push to the branch (`git push origin my-new-feature`)
66
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/rjp ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'ostruct'
4
+ require 'ap'
5
+ require 'rjp'
6
+
7
+ opts = OpenStruct.new(
8
+ keys: [],
9
+ default_value: nil,
10
+ post_processor: ->(value){ value }
11
+ )
12
+ option_parser = OptionParser.new do |options|
13
+ options.set_banner "Usage: rjp [options] [key/s] [file]\n" \
14
+ "Parse json to a ruby hash for data access."
15
+
16
+ options.separator ""
17
+ options.separator "Specific options:"
18
+
19
+ options.on("-k", "--keys x,y,z", Array, "Keys to fetch from document") do |keys|
20
+ opts.keys = keys
21
+ end
22
+
23
+ options.on("-d", "--default key", "Default value if key is missing.") do |default|
24
+ opts.default_value = default
25
+ end
26
+
27
+ options.on("-e", "--eval expression", "Code to evaluate using value or document.") do |code|
28
+ opts.post_processor = eval "->(value){ #{code} }"
29
+ end
30
+
31
+ options.on_tail("-h", "--help", "You're looking at it!") do
32
+ $stderr.puts options
33
+ exit 1
34
+ end
35
+ end
36
+ option_parser.parse!
37
+
38
+ input = ARGF.read
39
+ parser = Rjp.new input
40
+
41
+ output = if !opts.keys.empty?
42
+ if opts.default_value.nil?
43
+ parser.extract(*opts.keys)
44
+ else
45
+ parser.extract(*opts.keys) { opts.default_value }
46
+ end
47
+ else
48
+ parser.to_h
49
+ end
50
+ ap opts.post_processor.call(output)
data/lib/rjp.rb ADDED
@@ -0,0 +1,27 @@
1
+ require "rjp/version"
2
+ require 'rjp/traversable'
3
+ require 'json'
4
+
5
+ module Rjp
6
+ def self.new(*args)
7
+ Parser.new(*args)
8
+ end
9
+
10
+ class Parser
11
+ def initialize(json_str)
12
+ @raw = json_str
13
+ end
14
+
15
+ def extract(*keys, &block)
16
+ json.traverse(*keys, &block)
17
+ end
18
+
19
+ def to_h
20
+ json
21
+ end
22
+
23
+ def json
24
+ @json ||= Traversable.new(JSON.parse @raw)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ require 'delegate'
2
+
3
+ class Traversable < SimpleDelegator
4
+ def traverse(*args, &block)
5
+ args.inject(self) { |obj, arg|
6
+ arg = Float(arg).to_i if obj.kind_of? Array
7
+ obj.fetch(arg, &block)
8
+ }
9
+ end
10
+
11
+ def class
12
+ __getobj__.class
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module Rjp
2
+ VERSION = "0.0.1"
3
+ end
data/rjp.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rjp/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rjp"
8
+ spec.version = Rjp::VERSION
9
+ spec.authors = ["Tyler Dooling"]
10
+ spec.email = ["me@tylerdooling.com"]
11
+ spec.description = %q{A command line tool for formatting JSON and extracting values}
12
+ spec.summary = %q{A command line tool for formatting JSON and extracting values}
13
+ spec.homepage = "https://github.com/tylerdooling/rjp"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_dependency "awesome_print"
25
+ end
@@ -0,0 +1,28 @@
1
+ require 'rspec'
2
+ require 'rjp'
3
+
4
+ describe Rjp do
5
+ let(:json_string) { %({ "level1": #{level1}}) }
6
+ let(:level1) { %({ "level2" : #{level2} }) }
7
+ let(:level2) { '[ { "level3a": "level3a_value" }, { "level3b": "level3b_value" } ]' }
8
+ let(:rjp) { Rjp.new json_string }
9
+
10
+ it "parses json to a hash" do
11
+ expect(rjp.to_h).to eq(JSON.parse json_string)
12
+ end
13
+
14
+ describe '#extract' do
15
+ it "returns a value for a key" do
16
+ expect(rjp.extract('level1')).to eq(JSON.parse level1)
17
+ end
18
+
19
+ it "returns a value for an index" do
20
+ rjp = Rjp.new '[ "zero", "one"]'
21
+ expect(rjp.extract(0)).to eq('zero')
22
+ end
23
+
24
+ it "returns a value for a list of nested keys or indecies" do
25
+ expect(rjp.extract('level1', 'level2', 0, 'level3a')).to eq('level3a_value')
26
+ end
27
+ end
28
+ end
data/spec/rjp_spec.rb ADDED
@@ -0,0 +1,58 @@
1
+ require 'rspec'
2
+ require 'rjp'
3
+
4
+ describe 'rjp' do
5
+ let(:json_string) { %({"level1": #{level1}}) }
6
+ let(:level1) { %({ "level2" : #{level2} }) }
7
+ let(:level2) { %([ { "level3a": "level3a_value" }, { "level3b": "level3b_value" } ]) }
8
+ let(:rjp) { File.expand_path(File.join('..', '..', 'bin', 'rjp'), __FILE__) }
9
+
10
+ it "accepts stdin" do
11
+ expect(`echo '{ "key": "value" }' | #{rjp} -k key`).to eq(%("value"\n))
12
+ end
13
+
14
+ it "accepts file list" do
15
+ `echo '{ "key": "value" }' > /tmp/rjp_json_test`
16
+ expect(`#{rjp} -k key /tmp/rjp_json_test`).to eq(%("value"\n))
17
+ `rm /tmp/rjp_json_test`
18
+ end
19
+
20
+ it "outputs formated a hash to stdout" do
21
+ str=<<-hash
22
+ {
23
+ "level1" => {
24
+ "level2" => [
25
+ [0] {
26
+ "level3a" => "level3a_value"
27
+ },
28
+ [1] {
29
+ "level3b" => "level3b_value"
30
+ }
31
+ ]
32
+ }
33
+ }
34
+ hash
35
+ expect(`echo '#{json_string}' | #{rjp}`).to eq(str)
36
+ end
37
+
38
+ context "when --keys are provided" do
39
+ it "extracts the value from the hash" do
40
+ expect(`echo '#{json_string}' | #{rjp} -k level1,level2,0,level3a`).to eq(%("level3a_value"\n))
41
+ expect(`echo '#{json_string}' | #{rjp} --keys level1,level2,0,level3a`).to eq(%("level3a_value"\n))
42
+ end
43
+
44
+ context "when the key is not found" do
45
+ it "returns a non-zero status" do
46
+ `echo '#{json_string}' | #{rjp} -k level1,level2,something`
47
+ expect($?.exitstatus).to eq(1)
48
+ end
49
+
50
+ context "when --default is provided" do
51
+ it "it is returned" do
52
+ expect(`echo '#{json_string}' | #{rjp} -k something -d default`).to eq(%("default"\n))
53
+ expect(`echo '#{json_string}' | #{rjp} --keys something --default default`).to eq(%("default"\n))
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rjp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tyler Dooling
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: awesome_print
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: A command line tool for formatting JSON and extracting values
70
+ email:
71
+ - me@tylerdooling.com
72
+ executables:
73
+ - rjp
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - bin/rjp
83
+ - lib/rjp.rb
84
+ - lib/rjp/traversable.rb
85
+ - lib/rjp/version.rb
86
+ - rjp.gemspec
87
+ - spec/lib/rjp/rjp_spec.rb
88
+ - spec/rjp_spec.rb
89
+ homepage: https://github.com/tylerdooling/rjp
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 2.0.3
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: A command line tool for formatting JSON and extracting values
113
+ test_files:
114
+ - spec/lib/rjp/rjp_spec.rb
115
+ - spec/rjp_spec.rb