jsonpath 1.0.7 → 1.1.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a31bb2922acb2b1a6e84a6e640ee148eb1f40f9d8113751c6903149e472e99d9
4
- data.tar.gz: ab119c28fe07e14bfab16e5e2905d59ccf7e8154d5ff817d14a9db92215f8bd2
3
+ metadata.gz: ab3e08744fe7f8ba3b64670fee8f75a0fa4c9b339de8257f64cdc7ea24f26965
4
+ data.tar.gz: 447ce47a7c5df36c2fa290da5aafc77304d5e8db9318cfcac2b97dd9ae8c9c8c
5
5
  SHA512:
6
- metadata.gz: 4ede5f5c546e8ac46689b993ada2d6ed456ed9e9b1027023e421b8d27e99b3f785360a3fcf093a58be473a80ecca3485b709f23575be6b93fb71c2ae46f63966
7
- data.tar.gz: 021a544e520b944266c276b3b79ca53e0311df7ade212655282e4f3f03b9bca18aba5858148dc7de8ec3ca91be67dbd2f5554c4b6a73273c094d94dc31f5aa71
6
+ metadata.gz: 5b458262f098ceea595a91a981136141d0ed3f7ef9782d8a205f619be1bb60a7234af11229527ed9fc9ef3baafec323ad33850d87b4dc389ac482c14bb4aa05f
7
+ data.tar.gz: d1756aa04d5e07de855439aa0a4895078ab5c3c2c90c4c9ec755ba1da2ffb3fe11e59d1819e03f6a82e8670fd810b1c895da150a9d24176ddf4a86a54705fcbf
@@ -0,0 +1,31 @@
1
+ name: test
2
+ on:
3
+ - push
4
+ - pull_request
5
+ jobs:
6
+ test:
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ ruby-version:
11
+ - '2.5'
12
+ - '2.6'
13
+ - '2.7'
14
+ - ruby-head
15
+ - jruby-head
16
+ - truffleruby-head
17
+ runs-on:
18
+ - ubuntu-latest
19
+
20
+ runs-on: ${{ matrix.runs-on }}
21
+
22
+ steps:
23
+
24
+ - uses: actions/checkout@v2
25
+
26
+ - uses: ruby/setup-ruby@v1
27
+ with:
28
+ ruby-version: ${{ matrix.ruby-version }}
29
+ bundler-cache: true
30
+
31
+ - run: bundle exec rake test
data/.gitignore CHANGED
@@ -6,3 +6,5 @@ doc/*
6
6
  .DS_Store
7
7
  .idea
8
8
  vendor
9
+ .tags
10
+ *.gem
data/Gemfile CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  source 'http://rubygems.org'
4
4
  gemspec
5
- gem 'rubocop', require: true, group: :test
5
+ # gem 'rubocop', require: true, group: :test
6
6
  gem 'simplecov', require: false, group: :test
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,8 +15,8 @@ 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
 
@@ -40,8 +40,8 @@ json = <<-HERE_DOC
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
46
  ```ruby
47
47
  path = JsonPath.new('$..price')
@@ -54,14 +54,15 @@ 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
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
67
  ```ruby
67
68
  JsonPath.on(json, '$..author')
@@ -73,29 +74,36 @@ Of course the full JsonPath syntax is supported, such as array slices
73
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
84
  ```ruby
84
- JsonPath.new('$..price[?(@ < 10)]').on(json)
85
+ JsonPath.new("$..price[?(@ < 10)]").on(json)
85
86
  # => [8.95, 8.99]
87
+
88
+ JsonPath.new("$..book[?(@['price'] == 8.95 || @['price'] == 8.99)].title").on(json)
89
+ # => ["Sayings of the Century", "Moby Dick"]
90
+
91
+ JsonPath.new("$..book[?(@['price'] == 8.95 && @['price'] == 8.99)].title").on(json)
92
+ # => []
86
93
  ```
87
94
 
88
- There is a convenience method, `#first` that gives you the first element for a JSON object and path.
95
+ There is a convenience method, `#first` that gives you the first element for a
96
+ JSON object and path.
89
97
 
90
98
  ```ruby
91
- JsonPath.new('$..color').first(object)
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
105
  ```ruby
98
- enum = JsonPath.new('$..color')[object]
106
+ enum = JsonPath.new('$..color')[json]
99
107
  # => #<JsonPath::Enumerable:...>
100
108
  enum.first
101
109
  # => "red"
@@ -103,29 +111,77 @@ enum.any?{ |c| c == 'red' }
103
111
  # => true
104
112
  ```
105
113
 
106
- ### More examples
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:
107
121
 
108
- For more usage examples and variations on paths, please visit the tests. There are some more complex ones as well.
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
+ ```
109
131
 
110
- ### Conditional Operators Are Also Supported
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:
111
135
 
112
136
  ```ruby
113
- def test_or_operator
114
- assert_equal [@object['store']['book'][1], @object['store']['book'][3]], JsonPath.new("$..book[?(@['price'] == 13 || @['price'] == 23)]").on(@object)
115
- end
137
+ book_class = Struct.new(:title)
138
+ book = book_class.new("Sayings of the Century")
116
139
 
117
- def test_and_operator
118
- assert_equal [], JsonPath.new("$..book[?(@['price'] == 13 && @['price'] == 23)]").on(@object)
119
- end
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"
120
152
 
121
- def test_and_operator_with_more_results
122
- assert_equal [@object['store']['book'][1]], JsonPath.new("$..book[?(@['price'] < 23 && @['price'] > 9)]").on(@object)
123
- end
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
161
+
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", ...}]
124
179
  ```
125
180
 
126
181
  ### Selecting Values
127
182
 
128
- It's possible to select results once a query has been defined after the query. For example given this JSON data:
183
+ It's possible to select results once a query has been defined after the query. For
184
+ example given this JSON data:
129
185
 
130
186
  ```bash
131
187
  {
@@ -168,15 +224,10 @@ It's possible to select results once a query has been defined after the query. F
168
224
  ]
169
225
  ```
170
226
 
171
- ### Running an individual test
172
-
173
- ```ruby
174
- ruby -Ilib:../lib test/test_jsonpath.rb --name test_wildcard_on_intermediary_element_v6
175
- ```
176
-
177
227
  ### Manipulation
178
228
 
179
- 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.
180
231
 
181
232
  ```ruby
182
233
  JsonPath.for('{"candy":"lollipop"}').gsub('$..candy') {|v| "big turks" }.to_hash
@@ -188,7 +239,9 @@ The result will be
188
239
  {'candy' => 'big turks'}
189
240
  ```
190
241
 
191
- 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:
192
245
 
193
246
  ```ruby
194
247
  json = '{"candy":"lollipop","noncandy":null,"other":"things"}'
@@ -200,6 +253,49 @@ o = JsonPath.for(json).
200
253
  # => {"candy" => "big turks"}
201
254
  ```
202
255
 
256
+ ### Fetch all paths
257
+
258
+ To fetch all possible paths in given json, you can use `fetch_all_paths` method.
259
+
260
+ data:
261
+
262
+ ```bash
263
+ {
264
+ "store": {
265
+ "book": [
266
+ {
267
+ "category": "reference",
268
+ "author": "Nigel Rees"
269
+ },
270
+ {
271
+ "category": "fiction",
272
+ "author": "Evelyn Waugh"
273
+ }
274
+ ]
275
+ }
276
+ ```
277
+
278
+ ... and this query:
279
+
280
+ ```ruby
281
+ JsonPath.fetch_all_path(data)
282
+ ```
283
+
284
+ ... the result will be:
285
+
286
+ ```bash
287
+ ["$", "$.store", "$.store.book", "$.store.book[0].category", "$.store.book[0].author", "$.store.book[0]", "$.store.book[1].category", "$.store.book[1].author", "$.store.book[1]"]
288
+ ```
289
+
290
+
291
+
203
292
  # Contributions
204
293
 
205
- Please feel free to submit an Issue or a Pull Request any time you feel like you would like to contribute. Thank you!
294
+ Please feel free to submit an Issue or a Pull Request any time you feel like
295
+ you would like to contribute. Thank you!
296
+
297
+ ## Running an individual test
298
+
299
+ ```ruby
300
+ ruby -Ilib:../lib test/test_jsonpath.rb --name test_wildcard_on_intermediary_element_v6
301
+ ```
data/jsonpath.gemspec CHANGED
@@ -23,5 +23,6 @@ Gem::Specification.new do |s|
23
23
  s.add_development_dependency 'code_stats'
24
24
  s.add_development_dependency 'minitest', '~> 2.2.0'
25
25
  s.add_development_dependency 'phocus'
26
+ s.add_development_dependency 'racc'
26
27
  s.add_development_dependency 'rake'
27
28
  end
@@ -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
@@ -3,6 +3,7 @@
3
3
  class JsonPath
4
4
  class Enumerable
5
5
  include ::Enumerable
6
+ include Dig
6
7
 
7
8
  def initialize(path, object, mode, options = {})
8
9
  @path = path.path
@@ -12,12 +13,7 @@ class JsonPath
12
13
  end
13
14
 
14
15
  def each(context = @object, key = nil, pos = 0, &blk)
15
- node =
16
- if key
17
- context.is_a?(Hash) || context.is_a?(Array) ? context[key] : context.__send__(key)
18
- else
19
- context
20
- end
16
+ node = key ? dig_one(context, key) : context
21
17
  @_current_node = node
22
18
  return yield_value(blk, context, key) if pos == @path.size
23
19
 
@@ -47,11 +43,10 @@ class JsonPath
47
43
  def filter_context(context, keys)
48
44
  case context
49
45
  when Hash
50
- # TODO: Change this to `slice(*keys)` when ruby version support is > 2.4
51
- context.select { |k| keys.include?(k) }
46
+ dig_as_hash(context, keys)
52
47
  when Array
53
48
  context.each_with_object([]) do |c, memo|
54
- memo << c.select { |k| keys.include?(k) }
49
+ memo << dig_as_hash(c, keys)
55
50
  end
56
51
  end
57
52
  end
@@ -61,16 +56,14 @@ class JsonPath
61
56
  case sub_path[0]
62
57
  when '\'', '"'
63
58
  k = sub_path[1, sub_path.size - 2]
64
- if node.is_a?(Hash)
65
- node[k] ||= nil if @options[:default_path_leaf_to_null]
66
- each(node, k, pos + 1, &blk) if node.key?(k)
67
- elsif node.respond_to?(k.to_s) && !Object.respond_to?(k.to_s)
59
+ yield_if_diggable(node, k) do
68
60
  each(node, k, pos + 1, &blk)
69
61
  end
70
62
  when '?'
71
63
  handle_question_mark(sub_path, node, pos, &blk)
72
64
  else
73
65
  next if node.is_a?(Array) && node.empty?
66
+ next if node.nil? # when default_path_leaf_to_null is true
74
67
 
75
68
  array_args = sub_path.split(':')
76
69
  if array_args[0] == '*'
@@ -130,7 +123,7 @@ class JsonPath
130
123
  def yield_value(blk, context, key)
131
124
  case @mode
132
125
  when nil
133
- blk.call(key ? context[key] : context)
126
+ blk.call(key ? dig_one(context, key) : context)
134
127
  when :compact
135
128
  if key && context[key].nil?
136
129
  key.is_a?(Integer) ? context.delete_at(key) : context.delete(key)
@@ -158,16 +151,13 @@ class JsonPath
158
151
  identifiers = /@?((?<!\d)\.(?!\d)(\w+))+/.match(exp)
159
152
  if !identifiers.nil? && !@_current_node.methods.include?(identifiers[2].to_sym)
160
153
  exp_to_eval = exp.dup
161
- exp_to_eval[identifiers[0]] = identifiers[0].split('.').map do |el|
162
- el == '@' ? '@' : "['#{el}']"
163
- end.join
164
154
  begin
165
- return JsonPath::Parser.new(@_current_node).parse(exp_to_eval)
155
+ return JsonPath::Parser.new(@_current_node, @options).parse(exp_to_eval)
166
156
  rescue StandardError
167
157
  return default
168
158
  end
169
159
  end
170
- JsonPath::Parser.new(@_current_node).parse(exp)
160
+ JsonPath::Parser.new(@_current_node, @options).parse(exp)
171
161
  end
172
162
  end
173
163
  end
@@ -5,11 +5,14 @@ require 'strscan'
5
5
  class JsonPath
6
6
  # Parser parses and evaluates an expression passed to @_current_node.
7
7
  class Parser
8
+ include Dig
9
+
8
10
  REGEX = /\A\/(.+)\/([imxnesu]*)\z|\A%r{(.+)}([imxnesu]*)\z/
9
11
 
10
- def initialize(node)
12
+ def initialize(node, options)
11
13
  @_current_node = node
12
14
  @_expr_map = {}
15
+ @options = options
13
16
  end
14
17
 
15
18
  # parse will parse an expression in the following way.
@@ -65,7 +68,7 @@ class JsonPath
65
68
  scanner = StringScanner.new(exp)
66
69
  elements = []
67
70
  until scanner.eos?
68
- if (t = scanner.scan(/\['[a-zA-Z@&*\/$%^?_]+'\]|\.[a-zA-Z0-9_]+[?!]?/))
71
+ if (t = scanner.scan(/\['[a-zA-Z@&*\/$%^?_]+'\]|\.[a-zA-Z0-9_]+[?]?/))
69
72
  elements << t.gsub(/[\[\]'.]|\s+/, '')
70
73
  elsif (t = scanner.scan(/(\s+)?[<>=!\-+][=~]?(\s+)?/))
71
74
  operator = t
@@ -91,7 +94,7 @@ class JsonPath
91
94
  el = if elements.empty?
92
95
  @_current_node
93
96
  elsif @_current_node.is_a?(Hash)
94
- @_current_node.dig(*elements)
97
+ dig(@_current_node, *elements)
95
98
  else
96
99
  elements.inject(@_current_node, &:__send__)
97
100
  end
@@ -156,9 +159,11 @@ class JsonPath
156
159
  res = bool_or_exp(top.shift)
157
160
  top.each_with_index do |item, index|
158
161
  if item == '&&'
159
- res &&= top[index + 1]
162
+ next_value = bool_or_exp(top[index + 1])
163
+ res &&= next_value
160
164
  elsif item == '||'
161
- res ||= top[index + 1]
165
+ next_value = bool_or_exp(top[index + 1])
166
+ res ||= next_value
162
167
  end
163
168
  end
164
169
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonPath
4
- VERSION = '1.0.7'
4
+ VERSION = '1.1.2'
5
5
  end
data/lib/jsonpath.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require 'strscan'
4
4
  require 'multi_json'
5
5
  require 'jsonpath/proxy'
6
+ require 'jsonpath/dig'
6
7
  require 'jsonpath/enumerable'
7
8
  require 'jsonpath/version'
8
9
  require 'jsonpath/parser'
@@ -12,10 +13,18 @@ require 'jsonpath/parser'
12
13
  class JsonPath
13
14
  PATH_ALL = '$..*'
14
15
 
16
+ DEFAULT_OPTIONS = {
17
+ :default_path_leaf_to_null => false,
18
+ :symbolize_keys => false,
19
+ :use_symbols => false,
20
+ :allow_send => true,
21
+ :max_nesting => 100
22
+ }
23
+
15
24
  attr_accessor :path
16
25
 
17
26
  def initialize(path, opts = {})
18
- @opts = opts
27
+ @opts = DEFAULT_OPTIONS.merge(opts)
19
28
  scanner = StringScanner.new(path.strip)
20
29
  @path = []
21
30
  until scanner.eos?
@@ -78,13 +87,46 @@ class JsonPath
78
87
  end
79
88
  a
80
89
  end
90
+
91
+ def self.fetch_all_path(obj)
92
+ all_paths = ['$']
93
+ find_path(obj, '$', all_paths, obj.class == Array)
94
+ return all_paths
95
+ end
96
+
97
+ def self.find_path(obj, root_key, all_paths, is_array = false)
98
+ obj.each do |key, value|
99
+ table_params = { key: key, root_key: root_key}
100
+ is_loop = value.class == Array || value.class == Hash
101
+ if is_loop
102
+ path_exp = construct_path(table_params)
103
+ all_paths << path_exp
104
+ find_path(value, path_exp, all_paths, value.class == Array)
105
+ elsif is_array
106
+ table_params[:index] = obj.find_index(key)
107
+ path_exp = construct_path(table_params)
108
+ find_path(key, path_exp, all_paths, key.class == Array) if key.class == Hash || key.class == Array
109
+ all_paths << path_exp
110
+ else
111
+ all_paths << construct_path(table_params)
112
+ end
113
+ end
114
+ end
115
+
116
+ def self.construct_path(table_row)
117
+ if table_row[:index]
118
+ return table_row[:root_key] + '['+ table_row[:index].to_s + ']'
119
+ else
120
+ return table_row[:root_key] + '.'+ table_row[:key]
121
+ end
122
+ end
81
123
 
82
124
  def first(obj_or_str, *args)
83
125
  enum_on(obj_or_str).first(*args)
84
126
  end
85
127
 
86
128
  def enum_on(obj_or_str, mode = nil)
87
- JsonPath::Enumerable.new(self, self.class.process_object(obj_or_str), mode,
129
+ JsonPath::Enumerable.new(self, self.class.process_object(obj_or_str, @opts), mode,
88
130
  @opts)
89
131
  end
90
132
  alias [] enum_on
@@ -99,8 +141,8 @@ class JsonPath
99
141
 
100
142
  private
101
143
 
102
- def self.process_object(obj_or_str)
103
- obj_or_str.is_a?(String) ? MultiJson.decode(obj_or_str) : obj_or_str
144
+ def self.process_object(obj_or_str, opts = {})
145
+ obj_or_str.is_a?(String) ? MultiJson.decode(obj_or_str, max_nesting: opts[:max_nesting]) : obj_or_str
104
146
  end
105
147
 
106
148
  def deep_clone
@@ -70,24 +70,60 @@ class TestJsonpath < MiniTest::Unit::TestCase
70
70
  assert_equal [@object['store']['book'][0], @object['store']['book'][2]], JsonPath.new("$..book[?(@['price'] < 10)]").on(@object)
71
71
  assert_equal [@object['store']['book'][0], @object['store']['book'][2]], JsonPath.new("$..book[?(@['price'] == 9)]").on(@object)
72
72
  assert_equal [@object['store']['book'][3]], JsonPath.new("$..book[?(@['price'] > 20)]").on(@object)
73
- assert_equal [
74
- @object['store']['book'][0],
75
- @object['store']['book'][4],
76
- @object['store']['book'][5],
77
- @object['store']['book'][6]
78
- ], JsonPath.new("$..book[?(@['category'] != 'fiction')]").on(@object)
73
+ end
74
+
75
+ def test_not_equals_operator
76
+ expected =
77
+ [
78
+ @object['store']['book'][0],
79
+ @object['store']['book'][4],
80
+ @object['store']['book'][5],
81
+ @object['store']['book'][6]
82
+ ]
83
+ assert_equal(expected, JsonPath.new("$..book[?(@['category'] != 'fiction')]").on(@object))
84
+ assert_equal(expected, JsonPath.new("$..book[?(@['category']!=fiction)]").on(@object))
85
+ assert_equal(expected, JsonPath.new("$..book[?(@.category!=fiction)]").on(@object))
86
+ assert_equal(expected, JsonPath.new("$..book[?(@.category != 'fiction')]").on(@object))
79
87
  end
80
88
 
81
89
  def test_or_operator
82
90
  assert_equal [@object['store']['book'][1], @object['store']['book'][3]], JsonPath.new("$..book[?(@['price'] == 13 || @['price'] == 23)]").on(@object)
91
+ result = ["Sayings of the Century", "Sword of Honour", "Moby Dick", "The Lord of the Rings"]
92
+ assert_equal result, JsonPath.new("$..book[?(@.price==13 || @.price==9 || @.price==23)].title").on(@object)
93
+ assert_equal result, JsonPath.new("$..book[?(@.price==9 || @.price==23 || @.price==13)].title").on(@object)
94
+ assert_equal result, JsonPath.new("$..book[?(@.price==23 || @.price==13 || @.price==9)].title").on(@object)
95
+ end
96
+
97
+ def test_or_operator_with_not_equals
98
+ # Should be the same regardless of key style ( @.key vs @['key'] )
99
+ result = ['Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J. R. R. Tolkien', 'Lukyanenko']
100
+ assert_equal result, JsonPath.new("$..book[?(@['title']=='Osennie Vizity' || @['author']!='Lukyanenko')].author").on(@object)
101
+ assert_equal result, JsonPath.new("$..book[?(@.title=='Osennie Vizity' || @.author != Lukyanenko )].author").on(@object)
102
+ assert_equal result, JsonPath.new("$..book[?(@.title=='Osennie Vizity' || @.author!=Lukyanenko )].author").on(@object)
83
103
  end
84
104
 
85
105
  def test_and_operator
86
106
  assert_equal [], JsonPath.new("$..book[?(@['price'] == 13 && @['price'] == 23)]").on(@object)
107
+ assert_equal [], JsonPath.new("$..book[?(@.price>=13 && @.category==fiction && @.title==no_match)]").on(@object)
108
+ assert_equal [], JsonPath.new("$..book[?(@.title==no_match && @.category==fiction && @.price==13)]").on(@object)
109
+ assert_equal [], JsonPath.new("$..book[?(@.price==13 && @.title==no_match && @.category==fiction)]").on(@object)
110
+ assert_equal [], JsonPath.new("$..book[?(@.price==13 && @.bad_key_name==true && @.category==fiction)]").on(@object)
111
+
112
+ expected = [@object['store']['book'][1]]
113
+ assert_equal expected, JsonPath.new("$..book[?(@['price'] < 23 && @['price'] > 9)]").on(@object)
114
+ assert_equal expected, JsonPath.new("$..book[?(@.price < 23 && @.price > 9)]").on(@object)
115
+
116
+ expected = ['Sword of Honour', 'The Lord of the Rings']
117
+ assert_equal expected, JsonPath.new("$..book[?(@.price>=13 && @.category==fiction)].title").on(@object)
118
+ assert_equal ['The Lord of the Rings'], JsonPath.new("$..book[?(@.category==fiction && @.isbn && @.price>9)].title").on(@object)
119
+ assert_equal ['Sayings of the Century'], JsonPath.new("$..book[?(@['price'] == 9 && @.author=='Nigel Rees')].title").on(@object)
120
+ assert_equal ['Sayings of the Century'], JsonPath.new("$..book[?(@['price'] == 9 && @.tags..asdf)].title").on(@object)
87
121
  end
88
122
 
89
- def test_and_operator_with_more_results
90
- assert_equal [@object['store']['book'][1]], JsonPath.new("$..book[?(@['price'] < 23 && @['price'] > 9)]").on(@object)
123
+ def test_and_operator_with_not_equals
124
+ expected = ['Nigel Rees']
125
+ assert_equal expected, JsonPath.new("$..book[?(@['price']==9 && @['category']!=fiction)].author").on(@object)
126
+ assert_equal expected, JsonPath.new("$..book[?(@.price==9 && @.category!=fiction)].author").on(@object)
91
127
  end
92
128
 
93
129
  def test_nested_grouping
@@ -130,6 +166,50 @@ class TestJsonpath < MiniTest::Unit::TestCase
130
166
  assert_equal ['value'], JsonPath.new('$.b').on(object)
131
167
  end
132
168
 
169
+ def test_works_on_object
170
+ klass = Class.new{
171
+ attr_reader :b
172
+ def initialize(b)
173
+ @b = b
174
+ end
175
+ }
176
+ object = klass.new("value")
177
+
178
+ assert_equal ["value"], JsonPath.new('$.b').on(object)
179
+ end
180
+
181
+ def test_works_on_object_can_be_disabled
182
+ klass = Class.new{
183
+ attr_reader :b
184
+ def initialize(b)
185
+ @b = b
186
+ end
187
+ }
188
+ object = klass.new("value")
189
+
190
+ assert_equal [], JsonPath.new('$.b', allow_send: false).on(object)
191
+ end
192
+
193
+ def test_works_on_diggable
194
+ klass = Class.new{
195
+ attr_reader :h
196
+ def initialize(h)
197
+ @h = h
198
+ end
199
+ def dig(*keys)
200
+ @h.dig(*keys)
201
+ end
202
+ }
203
+
204
+ object = klass.new('a' => 'some', 'b' => 'value')
205
+ assert_equal ['value'], JsonPath.new('$.b').on(object)
206
+
207
+ object = {
208
+ "foo" => klass.new('a' => 'some', 'b' => 'value')
209
+ }
210
+ assert_equal ['value'], JsonPath.new('$.foo.b').on(object)
211
+ end
212
+
133
213
  def test_works_on_non_hash_with_filters
134
214
  klass = Struct.new(:a, :b)
135
215
  first_object = klass.new('some', 'value')
@@ -138,6 +218,24 @@ class TestJsonpath < MiniTest::Unit::TestCase
138
218
  assert_equal ['other value'], JsonPath.new('$[?(@.a == "next")].b').on([first_object, second_object])
139
219
  end
140
220
 
221
+ def test_works_on_hash_with_summary
222
+ object = {
223
+ "foo" => [{
224
+ "a" => "some",
225
+ "b" => "value"
226
+ }]
227
+ }
228
+ assert_equal [{ "b" => "value" }], JsonPath.new("$.foo[*](b)").on(object)
229
+ end
230
+
231
+ def test_works_on_non_hash_with_summary
232
+ klass = Struct.new(:a, :b)
233
+ object = {
234
+ "foo" => [klass.new("some", "value")]
235
+ }
236
+ assert_equal [{ "b" => "value" }], JsonPath.new("$.foo[*](b)").on(object)
237
+ end
238
+
141
239
  def test_recognize_array_with_evald_index
142
240
  assert_equal [@object['store']['book'][2]], JsonPath.new('$..book[(@.length-5)]').on(@object)
143
241
  end
@@ -508,11 +606,42 @@ class TestJsonpath < MiniTest::Unit::TestCase
508
606
  'name' => 'testname2'
509
607
  }]
510
608
  }
511
- assert_equal [{ 'isTrue' => true, 'name' => 'testname1' }], JsonPath.new('$.data[?(@.isTrue)]').on(data)
609
+
610
+ # These queries should be equivalent
611
+ expected = [{ 'isTrue' => true, 'name' => 'testname1' }]
612
+ assert_equal expected, JsonPath.new('$.data[?(@.isTrue)]').on(data)
613
+ assert_equal expected, JsonPath.new('$.data[?(@.isTrue==true)]').on(data)
614
+ assert_equal expected, JsonPath.new('$.data[?(@.isTrue == true)]').on(data)
615
+
616
+ # These queries should be equivalent
617
+ expected = [{ 'isTrue' => false, 'name' => 'testname2' }]
618
+ assert_equal expected, JsonPath.new('$.data[?(@.isTrue != true)]').on(data)
619
+ assert_equal expected, JsonPath.new('$.data[?(@.isTrue!=true)]').on(data)
620
+ assert_equal expected, JsonPath.new('$.data[?(@.isTrue==false)]').on(data)
621
+ end
622
+
623
+ def test_and_operator_with_boolean_parameter_value
624
+ data = {
625
+ 'data' => [{
626
+ 'hasProperty1' => true,
627
+ 'hasProperty2' => false,
628
+ 'name' => 'testname1'
629
+ }, {
630
+ 'hasProperty1' => false,
631
+ 'hasProperty2' => true,
632
+ 'name' => 'testname2'
633
+ }, {
634
+ 'hasProperty1' => true,
635
+ 'hasProperty2' => true,
636
+ 'name' => 'testname3'
637
+ }]
638
+ }
639
+ assert_equal ['testname3'], JsonPath.new('$.data[?(@.hasProperty1 && @.hasProperty2)].name').on(data)
512
640
  end
513
641
 
514
642
  def test_regex_simple
515
643
  assert_equal %w[asdf asdf2], JsonPath.new('$.store.book..tags[?(@ =~ /asdf/)]').on(@object)
644
+ assert_equal %w[asdf asdf2], JsonPath.new('$.store.book..tags[?(@=~/asdf/)]').on(@object)
516
645
  end
517
646
 
518
647
  def test_regex_simple_miss
@@ -849,7 +978,34 @@ class TestJsonpath < MiniTest::Unit::TestCase
849
978
  assert_equal [], JsonPath.on(json, "$.phoneNumbers[?(@[0].type == 'home')]")
850
979
  end
851
980
 
852
- def test_selecting_multiple_keys
981
+ def test_selecting_multiple_keys_on_hash
982
+ json = '
983
+ {
984
+ "category": "reference",
985
+ "author": "Nigel Rees",
986
+ "title": "Sayings of the Century",
987
+ "price": 8.95
988
+ }
989
+ '.to_json
990
+ assert_equal [{ 'category' => 'reference', 'author' => 'Nigel Rees' }], JsonPath.on(json, '$.(category,author)')
991
+ end
992
+
993
+ def test_selecting_multiple_keys_on_sub_hash
994
+ skip("Failing as the semantics of .(x,y) is unclear")
995
+ json = '
996
+ {
997
+ "book": {
998
+ "category": "reference",
999
+ "author": "Nigel Rees",
1000
+ "title": "Sayings of the Century",
1001
+ "price": 8.95
1002
+ }
1003
+ }
1004
+ '.to_json
1005
+ assert_equal [{ 'category' => 'reference', 'author' => 'Nigel Rees' }], JsonPath.on(json, '$.book.(category,author)')
1006
+ end
1007
+
1008
+ def test_selecting_multiple_keys_on_array
853
1009
  json = '
854
1010
  {
855
1011
  "store": {
@@ -874,7 +1030,7 @@ class TestJsonpath < MiniTest::Unit::TestCase
874
1030
  assert_equal [{ 'category' => 'reference', 'author' => 'Nigel Rees' }, { 'category' => 'fiction', 'author' => 'Evelyn Waugh' }], JsonPath.on(json, '$.store.book[*](category,author)')
875
1031
  end
876
1032
 
877
- def test_selecting_multiple_keys_with_filter
1033
+ def test_selecting_multiple_keys_on_array_with_filter
878
1034
  json = '
879
1035
  {
880
1036
  "store": {
@@ -925,6 +1081,32 @@ class TestJsonpath < MiniTest::Unit::TestCase
925
1081
  assert_equal [{ 'cate gory' => 'reference', 'author' => 'Nigel Rees' }], JsonPath.on(json, "$.store.book[?(@['price'] == 8.95)]( cate gory, author )")
926
1082
  end
927
1083
 
1084
+ def test_use_symbol_opt
1085
+ json = {
1086
+ store: {
1087
+ book: [
1088
+ {
1089
+ category: "reference",
1090
+ author: "Nigel Rees",
1091
+ title: "Sayings of the Century",
1092
+ price: 8.95
1093
+ },
1094
+ {
1095
+ category: "fiction",
1096
+ author: "Evelyn Waugh",
1097
+ title: "Sword of Honour",
1098
+ price: 12.99
1099
+ }
1100
+ ]
1101
+ }
1102
+ }
1103
+ on = ->(path){ JsonPath.on(json, path, use_symbols: true) }
1104
+ assert_equal ['reference', 'fiction'], on.("$.store.book[*].category")
1105
+ assert_equal ['reference', 'fiction'], on.("$..category")
1106
+ assert_equal ['reference'], on.("$.store.book[?(@['price'] == 8.95)].category")
1107
+ assert_equal [{'category' => 'reference'}], on.("$.store.book[?(@['price'] == 8.95)](category)")
1108
+ end
1109
+
928
1110
  def test_object_method_send
929
1111
  j = {height: 5, hash: "some_hash"}.to_json
930
1112
  hs = JsonPath.new "$..send"
@@ -945,6 +1127,70 @@ class TestJsonpath < MiniTest::Unit::TestCase
945
1127
  assert_equal ['foo'], JsonPath.new('$.1').on(data.to_json)
946
1128
  end
947
1129
 
1130
+ def test_behavior_on_null_and_missing
1131
+ data = {
1132
+ "foo" => nil,
1133
+ "bar" => {
1134
+ "baz" => nil
1135
+ },
1136
+ "bars" => [
1137
+ { "foo" => 12 },
1138
+ { "foo" => nil },
1139
+ { }
1140
+ ]
1141
+ }
1142
+ assert_equal [nil], JsonPath.new('$.foo').on(data)
1143
+ assert_equal [nil], JsonPath.new('$.bar.baz').on(data)
1144
+ assert_equal [], JsonPath.new('$.baz').on(data)
1145
+ assert_equal [], JsonPath.new('$.bar.foo').on(data)
1146
+ assert_equal [12, nil], JsonPath.new('$.bars[*].foo').on(data)
1147
+ end
1148
+
1149
+ def test_default_path_leaf_to_null_opt
1150
+ data = {
1151
+ "foo" => nil,
1152
+ "bar" => {
1153
+ "baz" => nil
1154
+ },
1155
+ "bars" => [
1156
+ { "foo" => 12 },
1157
+ { "foo" => nil },
1158
+ { }
1159
+ ]
1160
+ }
1161
+ assert_equal [nil], JsonPath.new('$.foo', default_path_leaf_to_null: true).on(data)
1162
+ assert_equal [nil], JsonPath.new('$.bar.baz', default_path_leaf_to_null: true).on(data)
1163
+ assert_equal [nil], JsonPath.new('$.baz', default_path_leaf_to_null: true).on(data)
1164
+ assert_equal [nil], JsonPath.new('$.bar.foo', default_path_leaf_to_null: true).on(data)
1165
+ assert_equal [12, nil, nil], JsonPath.new('$.bars[*].foo', default_path_leaf_to_null: true).on(data)
1166
+ end
1167
+
1168
+ def test_raise_max_nesting_error
1169
+ json = {
1170
+ a: {
1171
+ b: {
1172
+ c: {
1173
+ }
1174
+ }
1175
+ }
1176
+ }.to_json
1177
+
1178
+ assert_raises(MultiJson::ParseError) { JsonPath.new('$.a', max_nesting: 1).on(json) }
1179
+ end
1180
+
1181
+ def test_with_max_nesting_false
1182
+ json = {
1183
+ a: {
1184
+ b: {
1185
+ c: {
1186
+ }
1187
+ }
1188
+ }
1189
+ }.to_json
1190
+
1191
+ assert_equal [{}], JsonPath.new('$.a.b.c', max_nesting: false).on(json)
1192
+ end
1193
+
948
1194
  def example_object
949
1195
  { 'store' => {
950
1196
  'book' => [
@@ -999,4 +1245,19 @@ class TestJsonpath < MiniTest::Unit::TestCase
999
1245
  '_links' => { 'self' => {} }
1000
1246
  } }
1001
1247
  end
1248
+
1249
+ def test_fetch_all_path
1250
+ data = {
1251
+ "foo" => nil,
1252
+ "bar" => {
1253
+ "baz" => nil
1254
+ },
1255
+ "bars" => [
1256
+ { "foo" => 12 },
1257
+ { "foo" => nil },
1258
+ { }
1259
+ ]
1260
+ }
1261
+ assert_equal ["$", "$.foo", "$.bar", "$.bar.baz", "$.bars", "$.bars[0].foo", "$.bars[0]", "$.bars[1].foo", "$.bars[1]", "$.bars[2]"], JsonPath.fetch_all_path(data)
1262
+ end
1002
1263
  end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require 'phocus'
5
+ require 'jsonpath'
6
+ require 'json'
7
+
8
+ class TestJsonpathReadme < MiniTest::Unit::TestCase
9
+
10
+ def setup
11
+ @json = <<-HERE_DOC
12
+ {"store":
13
+ {"bicycle":
14
+ {"price":19.95, "color":"red"},
15
+ "book":[
16
+ {"price":8.95, "category":"reference", "title":"Sayings of the Century", "author":"Nigel Rees"},
17
+ {"price":12.99, "category":"fiction", "title":"Sword of Honour", "author":"Evelyn Waugh"},
18
+ {"price":8.99, "category":"fiction", "isbn":"0-553-21311-3", "title":"Moby Dick", "author":"Herman Melville","color":"blue"},
19
+ {"price":22.99, "category":"fiction", "isbn":"0-395-19395-8", "title":"The Lord of the Rings", "author":"Tolkien"}
20
+ ]
21
+ }
22
+ }
23
+ HERE_DOC
24
+ end
25
+ attr_reader :json
26
+
27
+ def test_library_section
28
+ path = JsonPath.new('$..price')
29
+ assert_equal [19.95, 8.95, 12.99, 8.99, 22.99], path.on(json)
30
+ assert_equal [18.88], path.on('{"books":[{"title":"A Tale of Two Somethings","price":18.88}]}')
31
+ assert_equal ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "Tolkien"], JsonPath.on(json, '$..author')
32
+ assert_equal [
33
+ {"price" => 8.95, "category" => "reference", "title" => "Sayings of the Century", "author" => "Nigel Rees"},
34
+ {"price" => 8.99, "category" => "fiction", "isbn" => "0-553-21311-3", "title" => "Moby Dick", "author" => "Herman Melville","color" => "blue"},
35
+ ], JsonPath.new('$..book[::2]').on(json)
36
+ assert_equal [8.95, 8.99], JsonPath.new("$..price[?(@ < 10)]").on(json)
37
+ assert_equal ["Sayings of the Century", "Moby Dick"], JsonPath.new("$..book[?(@['price'] == 8.95 || @['price'] == 8.99)].title").on(json)
38
+ assert_equal [], JsonPath.new("$..book[?(@['price'] == 8.95 && @['price'] == 8.99)].title").on(json)
39
+ assert_equal "red", JsonPath.new('$..color').first(json)
40
+ end
41
+
42
+ def test_library_section_enumerable
43
+ enum = JsonPath.new('$..color')[json]
44
+ assert_equal "red", enum.first
45
+ assert enum.any?{ |c| c == 'red' }
46
+ end
47
+
48
+ def test_ruby_structures_section
49
+ book = { title: "Sayings of the Century" }
50
+ assert_equal [], JsonPath.new('$.title').on(book)
51
+ assert_equal ["Sayings of the Century"], JsonPath.new('$.title', use_symbols: true).on(book)
52
+
53
+ book_class = Struct.new(:title)
54
+ book = book_class.new("Sayings of the Century")
55
+ assert_equal ["Sayings of the Century"], JsonPath.new('$.title').on(book)
56
+
57
+ book_class = Class.new{ attr_accessor :title }
58
+ book = book_class.new
59
+ book.title = "Sayings of the Century"
60
+ assert_equal ["Sayings of the Century"], JsonPath.new('$.title', allow_send: true).on(book)
61
+ end
62
+
63
+ def test_options_section
64
+ assert_equal ["0-553-21311-3", "0-395-19395-8"], JsonPath.new('$..book[*].isbn').on(json)
65
+ assert_equal [nil, nil, "0-553-21311-3", "0-395-19395-8"], JsonPath.new('$..book[*].isbn', default_path_leaf_to_null: true).on(json)
66
+
67
+ assert_equal ["price", "category", "title", "author"], JsonPath.new('$..book[0]').on(json).map(&:keys).flatten.uniq
68
+ assert_equal [:price, :category, :title, :author], JsonPath.new('$..book[0]').on(json, symbolize_keys: true).map(&:keys).flatten.uniq
69
+ end
70
+
71
+ def selecting_value_section
72
+ json = <<-HERE_DOC
73
+ {
74
+ "store": {
75
+ "book": [
76
+ {
77
+ "category": "reference",
78
+ "author": "Nigel Rees",
79
+ "title": "Sayings of the Century",
80
+ "price": 8.95
81
+ },
82
+ {
83
+ "category": "fiction",
84
+ "author": "Evelyn Waugh",
85
+ "title": "Sword of Honour",
86
+ "price": 12.99
87
+ }
88
+ ]
89
+ }
90
+ HERE_DOC
91
+ got = JsonPath.on(json, "$.store.book[*](category,author)")
92
+ expected = [
93
+ {
94
+ "category" => "reference",
95
+ "author" => "Nigel Rees"
96
+ },
97
+ {
98
+ "category" => "fiction",
99
+ "author" => "Evelyn Waugh"
100
+ }
101
+ ]
102
+ assert_equal expected, got
103
+ end
104
+
105
+ def test_manipulation_section
106
+ assert_equal({"candy" => "big turks"}, JsonPath.for('{"candy":"lollipop"}').gsub('$..candy') {|v| "big turks" }.to_hash)
107
+
108
+ json = '{"candy":"lollipop","noncandy":null,"other":"things"}'
109
+ o = JsonPath.for(json).
110
+ gsub('$..candy') {|v| "big turks" }.
111
+ compact.
112
+ delete('$..other').
113
+ to_hash
114
+ assert_equal({"candy" => "big turks"}, o)
115
+ end
116
+
117
+ end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonpath
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Hull
8
8
  - Gergely Brautigam
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-12-15 00:00:00.000000000 Z
12
+ date: 2022-04-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
@@ -81,6 +81,20 @@ dependencies:
81
81
  - - ">="
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: racc
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
84
98
  - !ruby/object:Gem::Dependency
85
99
  name: rake
86
100
  requirement: !ruby/object:Gem::Requirement
@@ -106,11 +120,11 @@ extra_rdoc_files:
106
120
  - README.md
107
121
  files:
108
122
  - ".gemtest"
123
+ - ".github/workflows/test.yml"
109
124
  - ".gitignore"
110
125
  - ".rspec"
111
126
  - ".rubocop.yml"
112
127
  - ".rubocop_todo.yml"
113
- - ".travis.yml"
114
128
  - Gemfile
115
129
  - LICENSE.md
116
130
  - README.md
@@ -118,17 +132,19 @@ files:
118
132
  - bin/jsonpath
119
133
  - jsonpath.gemspec
120
134
  - lib/jsonpath.rb
135
+ - lib/jsonpath/dig.rb
121
136
  - lib/jsonpath/enumerable.rb
122
137
  - lib/jsonpath/parser.rb
123
138
  - lib/jsonpath/proxy.rb
124
139
  - lib/jsonpath/version.rb
125
140
  - test/test_jsonpath.rb
126
141
  - test/test_jsonpath_bin.rb
142
+ - test/test_readme.rb
127
143
  homepage: https://github.com/joshbuddy/jsonpath
128
144
  licenses:
129
145
  - MIT
130
146
  metadata: {}
131
- post_install_message:
147
+ post_install_message:
132
148
  rdoc_options: []
133
149
  require_paths:
134
150
  - lib
@@ -143,8 +159,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
159
  - !ruby/object:Gem::Version
144
160
  version: '0'
145
161
  requirements: []
146
- rubygems_version: 3.0.3
147
- signing_key:
162
+ rubygems_version: 3.3.7
163
+ signing_key:
148
164
  specification_version: 4
149
165
  summary: Ruby implementation of http://goessner.net/articles/JsonPath/
150
166
  test_files: []
data/.travis.yml DELETED
@@ -1,8 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.5
4
- - 2.6
5
- - 2.7
6
- - ruby-head
7
- - jruby-head
8
- - truffleruby-head