jsonpath 0.5.8 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0605409a770fbb28dd1352fa92753e7707d0df96
4
- data.tar.gz: ed5e1e0c2fc22721d9d9a71ca5ec97f15e07bfe5
2
+ SHA256:
3
+ metadata.gz: 27b1b5e54ebef03b9cde7f447c1dc6fb8e411b4a28f5039426c87782b250ab1a
4
+ data.tar.gz: ae08f25885125bde4f301d905b9c6446bf0e922516aabce101a4e90088fd6e68
5
5
  SHA512:
6
- metadata.gz: d3471d1c6ffdd79d987edf7772c945b2c5c74cd614086cc49e57588d47c6135310fd9ca6660c0e5e711521c9863b189de1067c8656165d46bf266eb2522a9491
7
- data.tar.gz: 091adbef8dc29e30172d0016cf67e6035af094426fd405a45fff52e0292b45340f1aab1804b5291f918b0916fe2f02b252cb8fa2d97e2ee13dcd330645ac9cf8
6
+ metadata.gz: e4e778c37086407f3fb101b23c7f0507c48f0714ad2ae671d14ce52a2397e18f0f7433b8fa0fe651e503285002b4db1b70dad91ae4de1cf51b948f9ec736818b
7
+ data.tar.gz: b0dac82fcb16862190ae1405680d4779d6b3208d6ad31e25e5b0eb800877ca8bf56bae2789bac11452dfd872593071334205208bcb3a7320e3a8c0b94ba206c9
data/.gitignore CHANGED
@@ -3,3 +3,8 @@ Gemfile.lock
3
3
  coverage/*
4
4
  doc/*
5
5
  .yardoc
6
+ .DS_Store
7
+ .idea
8
+ vendor
9
+ .tags
10
+ *.gem
data/.rubocop.yml ADDED
@@ -0,0 +1 @@
1
+ inherit_from: .rubocop_todo.yml
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,127 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2019-01-25 09:23:04 +0100 using RuboCop version 0.63.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 15
10
+ # Configuration parameters: AllowSafeAssignment.
11
+ Lint/AssignmentInCondition:
12
+ Exclude:
13
+ - 'lib/jsonpath.rb'
14
+ - 'lib/jsonpath/parser.rb'
15
+
16
+ # Offense count: 1
17
+ Lint/IneffectiveAccessModifier:
18
+ Exclude:
19
+ - 'lib/jsonpath.rb'
20
+
21
+ # Offense count: 17
22
+ Metrics/AbcSize:
23
+ Max: 60
24
+
25
+ # Offense count: 2
26
+ # Configuration parameters: CountComments, ExcludedMethods.
27
+ # ExcludedMethods: refine
28
+ Metrics/BlockLength:
29
+ Max: 37
30
+
31
+ # Offense count: 1
32
+ # Configuration parameters: CountBlocks.
33
+ Metrics/BlockNesting:
34
+ Max: 4
35
+
36
+ # Offense count: 3
37
+ # Configuration parameters: CountComments.
38
+ Metrics/ClassLength:
39
+ Max: 739
40
+
41
+ # Offense count: 7
42
+ Metrics/CyclomaticComplexity:
43
+ Max: 20
44
+
45
+ # Offense count: 26
46
+ # Configuration parameters: CountComments, ExcludedMethods.
47
+ Metrics/MethodLength:
48
+ Max: 52
49
+
50
+ # Offense count: 1
51
+ # Configuration parameters: CountKeywordArgs.
52
+ Metrics/ParameterLists:
53
+ Max: 6
54
+
55
+ # Offense count: 6
56
+ Metrics/PerceivedComplexity:
57
+ Max: 21
58
+
59
+ # Offense count: 1
60
+ # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
61
+ # AllowedNames: io, id, to, by, on, in, at, ip, db
62
+ Naming/UncommunicativeMethodParamName:
63
+ Exclude:
64
+ - 'lib/jsonpath/parser.rb'
65
+
66
+ # Offense count: 15
67
+ # Configuration parameters: AllowedChars.
68
+ Style/AsciiComments:
69
+ Exclude:
70
+ - 'lib/jsonpath/parser.rb'
71
+
72
+ # Offense count: 2
73
+ Style/Documentation:
74
+ Exclude:
75
+ - 'spec/**/*'
76
+ - 'test/**/*'
77
+ - 'lib/jsonpath/enumerable.rb'
78
+ - 'lib/jsonpath/proxy.rb'
79
+
80
+ # Offense count: 3
81
+ # Configuration parameters: MinBodyLength.
82
+ Style/GuardClause:
83
+ Exclude:
84
+ - 'lib/jsonpath/enumerable.rb'
85
+ - 'lib/jsonpath/parser.rb'
86
+
87
+ # Offense count: 2
88
+ # Cop supports --auto-correct.
89
+ Style/IfUnlessModifier:
90
+ Exclude:
91
+ - 'lib/jsonpath/enumerable.rb'
92
+
93
+ # Offense count: 1
94
+ Style/MultipleComparison:
95
+ Exclude:
96
+ - 'lib/jsonpath/parser.rb'
97
+
98
+ # Offense count: 3
99
+ # Cop supports --auto-correct.
100
+ # Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods.
101
+ # SupportedStyles: predicate, comparison
102
+ Style/NumericPredicate:
103
+ Exclude:
104
+ - 'spec/**/*'
105
+ - 'lib/jsonpath/enumerable.rb'
106
+ - 'lib/jsonpath/parser.rb'
107
+
108
+ # Offense count: 3
109
+ # Cop supports --auto-correct.
110
+ # Configuration parameters: EnforcedStyle, AllowInnerSlashes.
111
+ # SupportedStyles: slashes, percent_r, mixed
112
+ Style/RegexpLiteral:
113
+ Exclude:
114
+ - 'lib/jsonpath/parser.rb'
115
+
116
+ # Offense count: 4
117
+ # Cop supports --auto-correct.
118
+ Style/RescueModifier:
119
+ Exclude:
120
+ - 'lib/jsonpath/enumerable.rb'
121
+ - 'lib/jsonpath/parser.rb'
122
+
123
+ # Offense count: 89
124
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
125
+ # URISchemes: http, https
126
+ Metrics/LineLength:
127
+ Max: 296
data/.travis.yml CHANGED
@@ -1,5 +1,8 @@
1
+ language: ruby
1
2
  rvm:
2
- - 1.9.2
3
- - 1.9.3
4
- - 2.0.0
5
- - jruby
3
+ - 2.5
4
+ - 2.6
5
+ - 2.7
6
+ - ruby-head
7
+ - jruby-head
8
+ - truffleruby-head
data/Gemfile CHANGED
@@ -1,2 +1,6 @@
1
- source "http://rubygems.org"
2
- gemspec
1
+ # frozen_string_literal: true
2
+
3
+ source 'http://rubygems.org'
4
+ gemspec
5
+ gem 'rubocop', require: true, group: :test
6
+ gem 'simplecov', require: false, group: :test
data/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Joshua Lin & Gergely Brautigam
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -4,8 +4,8 @@ This is an implementation of http://goessner.net/articles/JsonPath/.
4
4
 
5
5
  ## What is JsonPath?
6
6
 
7
- JsonPath is a way of addressing elements within a JSON object. Similar to xpath of yore, JsonPath lets you
8
- traverse a json object and manipulate or access it.
7
+ JsonPath is a way of addressing elements within a JSON object. Similar to xpath
8
+ of yore, JsonPath lets you traverse a json object and manipulate or access it.
9
9
 
10
10
  ## Usage
11
11
 
@@ -15,14 +15,14 @@ There is stand-alone usage through the binary `jsonpath`
15
15
 
16
16
  jsonpath [expression] (file|string)
17
17
 
18
- If you omit the second argument, it will read stdin, assuming one valid JSON object
19
- per line. Expression must be a valid jsonpath expression.
18
+ If you omit the second argument, it will read stdin, assuming one valid JSON
19
+ object per line. Expression must be a valid jsonpath expression.
20
20
 
21
21
  ### Library
22
22
 
23
23
  To use JsonPath as a library simply include and get goin'!
24
24
 
25
- ~~~~~ {ruby}
25
+ ```ruby
26
26
  require 'jsonpath'
27
27
 
28
28
  json = <<-HERE_DOC
@@ -38,90 +38,212 @@ json = <<-HERE_DOC
38
38
  }
39
39
  }
40
40
  HERE_DOC
41
- ~~~~~
41
+ ```
42
42
 
43
- Now that we have a JSON object, let's get all the prices present in the object. We create an object for the path
44
- in the following way.
43
+ Now that we have a JSON object, let's get all the prices present in the object.
44
+ We create an object for the path in the following way.
45
45
 
46
- ~~~~~ {ruby}
46
+ ```ruby
47
47
  path = JsonPath.new('$..price')
48
- ~~~~~
48
+ ```
49
49
 
50
50
  Now that we have a path, let's apply it to the object above.
51
51
 
52
- ~~~~~ {ruby}
52
+ ```ruby
53
53
  path.on(json)
54
54
  # => [19.95, 8.95, 12.99, 8.99, 22.99]
55
- ~~~~~
55
+ ```
56
56
 
57
- Or on some other object ...
57
+ Or reuse it later on some other object (thread safe) ...
58
58
 
59
- ~~~~~ {ruby}
59
+ ```ruby
60
60
  path.on('{"books":[{"title":"A Tale of Two Somethings","price":18.88}]}')
61
61
  # => [18.88]
62
- ~~~~~
62
+ ```
63
63
 
64
- You can also just combine this into one mega-call with the convenient `JsonPath.on` method.
64
+ You can also just combine this into one mega-call with the convenient
65
+ `JsonPath.on` method.
65
66
 
66
- ~~~~~ {ruby}
67
+ ```ruby
67
68
  JsonPath.on(json, '$..author')
68
69
  # => ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "Tolkien"]
69
- ~~~~~
70
+ ```
70
71
 
71
72
  Of course the full JsonPath syntax is supported, such as array slices
72
73
 
73
- ~~~~~ {ruby}
74
+ ```ruby
74
75
  JsonPath.new('$..book[::2]').on(json)
75
76
  # => [
76
- # {"price"=>8.95, "category"=>"reference", "author"=>"Nigel Rees", "title"=>"Sayings of the Century"},
77
- # {"price"=>8.99, "category"=>"fiction", "author"=>"Herman Melville", "title"=>"Moby Dick", "isbn"=>"0-553-21311-3"}
77
+ # {"price" => 8.95, "category" => "reference", "title" => "Sayings of the Century", "author" => "Nigel Rees"},
78
+ # {"price" => 8.99, "category" => "fiction", "isbn" => "0-553-21311-3", "title" => "Moby Dick", "author" => "Herman Melville","color" => "blue"},
78
79
  # ]
79
- ~~~~~
80
+ ```
80
81
 
81
- ...and evals.
82
+ ...and evals, including those with conditional operators
82
83
 
83
- ~~~~~ {ruby}
84
- JsonPath.new('$..price[?(@ < 20)]').on(json)
84
+ ```ruby
85
+ JsonPath.new("$..price[?(@ < 10)]").on(json)
85
86
  # => [8.95, 8.99]
86
- ~~~~~
87
87
 
88
- There is a convenience method, `#first` that gives you the first element for a JSON object and path.
88
+ JsonPath.new("$..book[?(@['price'] == 8.95 || @['price'] == 8.99)].title").on(json)
89
+ # => ["Sayings of the Century", "Moby Dick"]
89
90
 
90
- ~~~~~ {ruby}
91
- JsonPath.new('$..color').first(object)
91
+ JsonPath.new("$..book[?(@['price'] == 8.95 && @['price'] == 8.99)].title").on(json)
92
+ # => []
93
+ ```
94
+
95
+ There is a convenience method, `#first` that gives you the first element for a
96
+ JSON object and path.
97
+
98
+ ```ruby
99
+ JsonPath.new('$..color').first(json)
92
100
  # => "red"
93
- ~~~~~
101
+ ```
94
102
 
95
103
  As well, we can directly create an `Enumerable` at any time using `#[]`.
96
104
 
97
- ~~~~~ {ruby}
98
- enum = JsonPath.new('$..color')[object]
105
+ ```ruby
106
+ enum = JsonPath.new('$..color')[json]
99
107
  # => #<JsonPath::Enumerable:...>
100
108
  enum.first
101
109
  # => "red"
102
110
  enum.any?{ |c| c == 'red' }
103
111
  # => true
104
- ~~~~~
112
+ ```
113
+
114
+ For more usage examples and variations on paths, please visit the tests. There
115
+ are some more complex ones as well.
116
+
117
+ ### Querying ruby data structures
118
+
119
+ If you have ruby hashes with symbolized keys as input, you
120
+ can use `:use_symbols` to make JsonPath work fine on them too:
121
+
122
+ ```ruby
123
+ book = { title: "Sayings of the Century" }
124
+
125
+ JsonPath.new('$.title').on(book)
126
+ # => []
127
+
128
+ JsonPath.new('$.title', use_symbols: true).on(book)
129
+ # => ["Sayings of the Century"]
130
+ ```
131
+
132
+ JsonPath also recognizes objects responding to `dig` (introduced
133
+ in ruby 2.3), and therefore works out of the box with Struct,
134
+ OpenStruct, and other Hash-like structures:
135
+
136
+ ```ruby
137
+ book_class = Struct.new(:title)
138
+ book = book_class.new("Sayings of the Century")
139
+
140
+ JsonPath.new('$.title').on(book)
141
+ # => ["Sayings of the Century"]
142
+ ```
143
+
144
+ JsonPath is able to query pure ruby objects and uses `__send__`
145
+ on them. The option is enabled by default in JsonPath 1.x, but
146
+ we encourage to enable it explicitly:
147
+
148
+ ```ruby
149
+ book_class = Class.new{ attr_accessor :title }
150
+ book = book_class.new
151
+ book.title = "Sayings of the Century"
152
+
153
+ JsonPath.new('$.title', allow_send: true).on(book)
154
+ # => ["Sayings of the Century"]
155
+ ```
156
+
157
+ ### Other available options
158
+
159
+ By default, JsonPath does not return null values on unexisting paths.
160
+ This can be changed using the `:default_path_leaf_to_null` option
105
161
 
106
- You can optionally prevent eval from being called on sub-expressions by passing in :allow_eval => false to the constructor.
162
+ ```ruby
163
+ JsonPath.new('$..book[*].isbn').on(json)
164
+ # => ["0-553-21311-3", "0-395-19395-8"]
165
+
166
+ JsonPath.new('$..book[*].isbn', default_path_leaf_to_null: true).on(json)
167
+ # => [nil, nil, "0-553-21311-3", "0-395-19395-8"]
168
+ ```
169
+
170
+ When JsonPath returns a Hash, you can ask to symbolize its keys
171
+ using the `:symbolize_keys` option
172
+
173
+ ```ruby
174
+ JsonPath.new('$..book[0]').on(json)
175
+ # => [{"category" => "reference", ...}]
176
+
177
+ JsonPath.new('$..book[0]', symbolize_keys: true).on(json)
178
+ # => [{category: "reference", ...}]
179
+ ```
180
+
181
+ ### Selecting Values
182
+
183
+ It's possible to select results once a query has been defined after the query. For
184
+ example given this JSON data:
185
+
186
+ ```bash
187
+ {
188
+ "store": {
189
+ "book": [
190
+ {
191
+ "category": "reference",
192
+ "author": "Nigel Rees",
193
+ "title": "Sayings of the Century",
194
+ "price": 8.95
195
+ },
196
+ {
197
+ "category": "fiction",
198
+ "author": "Evelyn Waugh",
199
+ "title": "Sword of Honour",
200
+ "price": 12.99
201
+ }
202
+ ]
203
+ }
204
+ ```
205
+
206
+ ... and this query:
207
+
208
+ ```ruby
209
+ "$.store.book[*](category,author)"
210
+ ```
211
+
212
+ ... the result can be filtered as such:
213
+
214
+ ```bash
215
+ [
216
+ {
217
+ "category" : "reference",
218
+ "author" : "Nigel Rees"
219
+ },
220
+ {
221
+ "category" : "fiction",
222
+ "author" : "Evelyn Waugh"
223
+ }
224
+ ]
225
+ ```
107
226
 
108
227
  ### Manipulation
109
228
 
110
- If you'd like to do substitution in a json object, you can use `#gsub` or `#gsub!` to modify the object in place.
229
+ If you'd like to do substitution in a json object, you can use `#gsub`
230
+ or `#gsub!` to modify the object in place.
111
231
 
112
- ~~~~~ {ruby}
232
+ ```ruby
113
233
  JsonPath.for('{"candy":"lollipop"}').gsub('$..candy') {|v| "big turks" }.to_hash
114
- ~~~~~
234
+ ```
115
235
 
116
236
  The result will be
117
237
 
118
- ~~~~~ {ruby}
238
+ ```ruby
119
239
  {'candy' => 'big turks'}
120
- ~~~~~
240
+ ```
121
241
 
122
- If you'd like to remove all nil keys, you can use `#compact` and `#compact!`. To remove all keys under a certain path, use `#delete` or `#delete!`. You can even chain these methods together as follows:
242
+ If you'd like to remove all nil keys, you can use `#compact` and `#compact!`.
243
+ To remove all keys under a certain path, use `#delete` or `#delete!`. You can
244
+ even chain these methods together as follows:
123
245
 
124
- ~~~~~ {ruby}
246
+ ```ruby
125
247
  json = '{"candy":"lollipop","noncandy":null,"other":"things"}'
126
248
  o = JsonPath.for(json).
127
249
  gsub('$..candy') {|v| "big turks" }.
@@ -129,4 +251,15 @@ o = JsonPath.for(json).
129
251
  delete('$..other').
130
252
  to_hash
131
253
  # => {"candy" => "big turks"}
132
- ~~~~~
254
+ ```
255
+
256
+ # Contributions
257
+
258
+ Please feel free to submit an Issue or a Pull Request any time you feel like
259
+ you would like to contribute. Thank you!
260
+
261
+ ## Running an individual test
262
+
263
+ ```ruby
264
+ ruby -Ilib:../lib test/test_jsonpath.rb --name test_wildcard_on_intermediary_element_v6
265
+ ```
data/Rakefile CHANGED
@@ -1,12 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ desc 'run rubocop'
4
+ task(:rubocop) do
5
+ require 'rubocop'
6
+ cli = RuboCop::CLI.new
7
+ cli.run
8
+ end
9
+
10
+ require 'simplecov'
11
+ SimpleCov.start do
12
+ add_filter '/test/'
13
+ end
14
+
1
15
  require 'bundler'
2
16
  Bundler::GemHelper.install_tasks
3
17
 
4
18
  task :test do
5
- $: << 'lib'
6
- require 'minitest/autorun'
7
- require 'phocus'
8
- require 'jsonpath'
19
+ $LOAD_PATH << 'lib'
9
20
  Dir['./test/**/test_*.rb'].each { |test| require test }
10
21
  end
11
22
 
12
- task :default => :test
23
+ task default: %i[test rubocop]
data/bin/jsonpath CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'jsonpath'
4
5
  require 'multi_json'
@@ -15,7 +16,7 @@ usage unless ARGV[0]
15
16
 
16
17
  jsonpath = JsonPath.new(ARGV[0])
17
18
  case ARGV[1]
18
- when nil #stdin
19
+ when nil # stdin
19
20
  puts MultiJson.encode(jsonpath.on(MultiJson.decode(STDIN.read)))
20
21
  when String
21
22
  puts MultiJson.encode(jsonpath.on(MultiJson.decode(File.exist?(ARGV[1]) ? File.read(ARGV[1]) : ARGV[1])))
data/jsonpath.gemspec CHANGED
@@ -1,32 +1,27 @@
1
- # -*- encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require File.join(File.dirname(__FILE__), 'lib', 'jsonpath', 'version')
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'jsonpath'
7
7
  s.version = JsonPath::VERSION
8
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9
- s.authors = ["Joshua Hull"]
10
- s.summary = "Ruby implementation of http://goessner.net/articles/JsonPath/"
11
- s.description = "Ruby implementation of http://goessner.net/articles/JsonPath/."
12
- s.email = %q{joshbuddy@gmail.com}
8
+ s.required_ruby_version = '>= 2.5'
9
+ s.authors = ['Joshua Hull', 'Gergely Brautigam']
10
+ s.summary = 'Ruby implementation of http://goessner.net/articles/JsonPath/'
11
+ s.description = 'Ruby implementation of http://goessner.net/articles/JsonPath/.'
12
+ s.email = ['joshbuddy@gmail.com', 'skarlso777@gmail.com']
13
13
  s.extra_rdoc_files = ['README.md']
14
14
  s.files = `git ls-files`.split("\n")
15
- s.homepage = %q{http://github.com/joshbuddy/jsonpath}
16
- s.rdoc_options = ["--charset=UTF-8"]
17
- s.require_paths = ["lib"]
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
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
15
+ s.homepage = 'https://github.com/joshbuddy/jsonpath'
16
+ s.test_files = `git ls-files`.split("\n").select { |f| f =~ /^spec/ }
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
22
18
  s.licenses = ['MIT']
23
19
 
24
20
  # dependencies
25
21
  s.add_runtime_dependency 'multi_json'
22
+ s.add_development_dependency 'bundler'
26
23
  s.add_development_dependency 'code_stats'
27
- s.add_development_dependency 'rake'
28
24
  s.add_development_dependency 'minitest', '~> 2.2.0'
29
25
  s.add_development_dependency 'phocus'
30
- s.add_development_dependency 'bundler'
26
+ s.add_development_dependency 'rake'
31
27
  end
32
-
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ class JsonPath
4
+ module Dig
5
+
6
+ # Similar to what Hash#dig or Array#dig
7
+ def dig(context, *keys)
8
+ keys.inject(context){|memo,k|
9
+ dig_one(memo, k)
10
+ }
11
+ end
12
+
13
+ # Returns a hash mapping each key from keys
14
+ # to its dig value on context.
15
+ def dig_as_hash(context, keys)
16
+ keys.each_with_object({}) do |k, memo|
17
+ memo[k] = dig_one(context, k)
18
+ end
19
+ end
20
+
21
+ # Dig the value of k on context.
22
+ def dig_one(context, k)
23
+ case context
24
+ when Hash
25
+ context[@options[:use_symbols] ? k.to_sym : k]
26
+ when Array
27
+ context[k.to_i]
28
+ else
29
+ if context.respond_to?(:dig)
30
+ context.dig(k)
31
+ elsif @options[:allow_send]
32
+ context.__send__(k)
33
+ end
34
+ end
35
+ end
36
+
37
+ # Yields the block if context has a diggable
38
+ # value for k
39
+ def yield_if_diggable(context, k, &blk)
40
+ case context
41
+ when Array
42
+ nil
43
+ when Hash
44
+ k = @options[:use_symbols] ? k.to_sym : k
45
+ return yield if context.key?(k) || @options[:default_path_leaf_to_null]
46
+ else
47
+ if context.respond_to?(:dig)
48
+ digged = dig_one(context, k)
49
+ yield if !digged.nil? || @options[:default_path_leaf_to_null]
50
+ elsif @options[:allow_send] && context.respond_to?(k.to_s) && !Object.respond_to?(k.to_s)
51
+ yield
52
+ end
53
+ end
54
+ end
55
+
56
+ end
57
+ end