iso-jsonpath 1.1.6

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,1334 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require 'phocus'
5
+ require 'jsonpath'
6
+ require 'json'
7
+
8
+ class TestJsonpath < MiniTest::Unit::TestCase
9
+ def setup
10
+ @object = example_object
11
+ @object2 = example_object
12
+ end
13
+
14
+ def test_bracket_matching
15
+ assert_raises(ArgumentError) { JsonPath.new('$.store.book[0') }
16
+ assert_raises(ArgumentError) { JsonPath.new('$.store.book[0]]') }
17
+ assert_equal [9], JsonPath.new('$.store.book[0].price').on(@object)
18
+ end
19
+
20
+ def test_lookup_direct_path
21
+ assert_equal 7, JsonPath.new('$.store.*').on(@object).first['book'].size
22
+ end
23
+
24
+ def test_lookup_missing_element
25
+ assert_equal [], JsonPath.new('$.store.book[99].price').on(@object)
26
+ end
27
+
28
+ def test_retrieve_all_authors
29
+ assert_equal [
30
+ @object['store']['book'][0]['author'],
31
+ @object['store']['book'][1]['author'],
32
+ @object['store']['book'][2]['author'],
33
+ @object['store']['book'][3]['author'],
34
+ @object['store']['book'][4]['author'],
35
+ @object['store']['book'][5]['author'],
36
+ @object['store']['book'][6]['author']
37
+ ], JsonPath.new('$..author').on(@object)
38
+ end
39
+
40
+ def test_retrieve_all_prices
41
+ assert_equal [
42
+ @object['store']['bicycle']['price'],
43
+ @object['store']['book'][0]['price'],
44
+ @object['store']['book'][1]['price'],
45
+ @object['store']['book'][2]['price'],
46
+ @object['store']['book'][3]['price']
47
+ ].sort, JsonPath.new('$..price').on(@object).sort
48
+ end
49
+
50
+ def test_recognize_array_splices
51
+ assert_equal [@object['store']['book'][0]], JsonPath.new('$..book[0:1:1]').on(@object)
52
+ assert_equal [@object['store']['book'][0], @object['store']['book'][1]], JsonPath.new('$..book[0:2:1]').on(@object)
53
+ assert_equal [@object['store']['book'][1], @object['store']['book'][3], @object['store']['book'][5]], JsonPath.new('$..book[1::2]').on(@object)
54
+ assert_equal [@object['store']['book'][0], @object['store']['book'][2], @object['store']['book'][4], @object['store']['book'][6]], JsonPath.new('$..book[::2]').on(@object)
55
+ assert_equal [@object['store']['book'][0], @object['store']['book'][2]], JsonPath.new('$..book[:-5:2]').on(@object)
56
+ assert_equal [@object['store']['book'][5], @object['store']['book'][6]], JsonPath.new('$..book[5::]').on(@object)
57
+ end
58
+
59
+ def test_slice_array_with_exclusive_end_correctly
60
+ assert_equal [@object['store']['book'][0], @object['store']['book'][1]], JsonPath.new('$..book[:2]').on(@object)
61
+ end
62
+
63
+ def test_recognize_array_comma
64
+ assert_equal [@object['store']['book'][0], @object['store']['book'][1]], JsonPath.new('$..book[0,1]').on(@object)
65
+ assert_equal [@object['store']['book'][2], @object['store']['book'][6]], JsonPath.new('$..book[2,-1::]').on(@object)
66
+ end
67
+
68
+ def test_recognize_filters
69
+ assert_equal [@object['store']['book'][2], @object['store']['book'][3]], JsonPath.new("$..book[?(@['isbn'])]").on(@object)
70
+ assert_equal [@object['store']['book'][0], @object['store']['book'][1]], JsonPath.new("$..book[?(@['year published'])]").on(@object)
71
+ assert_equal [@object['store']['book'][0], @object['store']['book'][2]], JsonPath.new("$..book[?(@['price'] < 10)]").on(@object)
72
+ assert_equal [@object['store']['book'][0], @object['store']['book'][2]], JsonPath.new("$..book[?(@['price'] == 9)]").on(@object)
73
+ assert_equal [@object['store']['book'][3]], JsonPath.new("$..book[?(@['price'] > 20)]").on(@object)
74
+ end
75
+
76
+ def test_not_equals_operator
77
+ expected =
78
+ [
79
+ @object['store']['book'][0],
80
+ @object['store']['book'][4],
81
+ @object['store']['book'][5],
82
+ @object['store']['book'][6]
83
+ ]
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))
87
+ assert_equal(expected, JsonPath.new("$..book[?(@.category != 'fiction')]").on(@object))
88
+ end
89
+
90
+ def test_or_operator
91
+ assert_equal [@object['store']['book'][1], @object['store']['book'][3]], JsonPath.new("$..book[?(@['price'] == 13 || @['price'] == 23)]").on(@object)
92
+ result = ["Sayings of the Century", "Sword of Honour", "Moby Dick", "The Lord of the Rings"]
93
+ assert_equal result, JsonPath.new("$..book[?(@.price==13 || @.price==9 || @.price==23)].title").on(@object)
94
+ assert_equal result, JsonPath.new("$..book[?(@.price==9 || @.price==23 || @.price==13)].title").on(@object)
95
+ assert_equal result, JsonPath.new("$..book[?(@.price==23 || @.price==13 || @.price==9)].title").on(@object)
96
+ end
97
+
98
+ def test_or_operator_with_not_equals
99
+ # Should be the same regardless of key style ( @.key vs @['key'] )
100
+ result = ['Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J. R. R. Tolkien', 'Lukyanenko']
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)
103
+ assert_equal result, JsonPath.new("$..book[?(@.title=='Osennie Vizity' || @.author!=Lukyanenko )].author").on(@object)
104
+ end
105
+
106
+ def test_and_operator
107
+ assert_equal [], JsonPath.new("$..book[?(@['price'] == 13 && @['price'] == 23)]").on(@object)
108
+ assert_equal [], JsonPath.new("$..book[?(@.price>=13 && @.category==fiction && @.title==no_match)]").on(@object)
109
+ assert_equal [], JsonPath.new("$..book[?(@.title==no_match && @.category==fiction && @.price==13)]").on(@object)
110
+ assert_equal [], JsonPath.new("$..book[?(@.price==13 && @.title==no_match && @.category==fiction)]").on(@object)
111
+ assert_equal [], JsonPath.new("$..book[?(@.price==13 && @.bad_key_name==true && @.category==fiction)]").on(@object)
112
+
113
+ expected = [@object['store']['book'][1]]
114
+ assert_equal expected, JsonPath.new("$..book[?(@['price'] < 23 && @['price'] > 9)]").on(@object)
115
+ assert_equal expected, JsonPath.new("$..book[?(@.price < 23 && @.price > 9)]").on(@object)
116
+
117
+ expected = ['Sword of Honour', 'The Lord of the Rings']
118
+ assert_equal expected, JsonPath.new("$..book[?(@.price>=13 && @.category==fiction)].title").on(@object)
119
+ assert_equal ['The Lord of the Rings'], JsonPath.new("$..book[?(@.category==fiction && @.isbn && @.price>9)].title").on(@object)
120
+ assert_equal ['Sayings of the Century'], JsonPath.new("$..book[?(@['price'] == 9 && @.author=='Nigel Rees')].title").on(@object)
121
+ assert_equal ['Sayings of the Century'], JsonPath.new("$..book[?(@['price'] == 9 && @.tags..asdf)].title").on(@object)
122
+ end
123
+
124
+ def test_and_operator_with_not_equals
125
+ expected = ['Nigel Rees']
126
+ assert_equal expected, JsonPath.new("$..book[?(@['price']==9 && @['category']!=fiction)].author").on(@object)
127
+ assert_equal expected, JsonPath.new("$..book[?(@.price==9 && @.category!=fiction)].author").on(@object)
128
+ end
129
+
130
+ def test_nested_grouping
131
+ path = "$..book[?((@['price'] == 19 && @['author'] == 'Herman Melville') || @['price'] == 23)]"
132
+ assert_equal [@object['store']['book'][3]], JsonPath.new(path).on(@object)
133
+ end
134
+
135
+ def test_eval_with_floating_point_and_and
136
+ assert_equal [@object['store']['book'][1]], JsonPath.new("$..book[?(@['price'] < 23.0 && @['price'] > 9.0)]").on(@object)
137
+ end
138
+
139
+ def test_eval_with_floating_point
140
+ assert_equal [@object['store']['book'][1]], JsonPath.new("$..book[?(@['price'] == 13.0)]").on(@object)
141
+ end
142
+
143
+ def test_paths_with_underscores
144
+ assert_equal [@object['store']['bicycle']['catalogue_number']], JsonPath.new('$.store.bicycle.catalogue_number').on(@object)
145
+ end
146
+
147
+ def test_path_with_hyphens
148
+ assert_equal [@object['store']['bicycle']['single-speed']], JsonPath.new('$.store.bicycle.single-speed').on(@object)
149
+ end
150
+
151
+ def test_path_with_colon
152
+ assert_equal [@object['store']['bicycle']['make:model']], JsonPath.new('$.store.bicycle.make:model').on(@object)
153
+ end
154
+
155
+ def test_paths_with_numbers
156
+ assert_equal [@object['store']['bicycle']['2seater']], JsonPath.new('$.store.bicycle.2seater').on(@object)
157
+ end
158
+
159
+ def test_recognized_dot_notation_in_filters
160
+ assert_equal [@object['store']['book'][2], @object['store']['book'][3]], JsonPath.new('$..book[?(@.isbn)]').on(@object)
161
+ end
162
+
163
+ def test_works_on_non_hash
164
+ klass = Struct.new(:a, :b)
165
+ object = klass.new('some', 'value')
166
+
167
+ assert_equal ['value'], JsonPath.new('$.b').on(object)
168
+ end
169
+
170
+ def test_works_on_object
171
+ klass = Class.new{
172
+ attr_reader :b
173
+ def initialize(b)
174
+ @b = b
175
+ end
176
+ }
177
+ object = klass.new("value")
178
+
179
+ assert_equal ["value"], JsonPath.new('$.b').on(object)
180
+ end
181
+
182
+ def test_works_on_object_can_be_disabled
183
+ klass = Class.new{
184
+ attr_reader :b
185
+ def initialize(b)
186
+ @b = b
187
+ end
188
+ }
189
+ object = klass.new("value")
190
+
191
+ assert_equal [], JsonPath.new('$.b', allow_send: false).on(object)
192
+ end
193
+
194
+ def test_works_on_diggable
195
+ klass = Class.new{
196
+ attr_reader :h
197
+ def initialize(h)
198
+ @h = h
199
+ end
200
+ def dig(*keys)
201
+ @h.dig(*keys)
202
+ end
203
+ }
204
+
205
+ object = klass.new('a' => 'some', 'b' => 'value')
206
+ assert_equal ['value'], JsonPath.new('$.b').on(object)
207
+
208
+ object = {
209
+ "foo" => klass.new('a' => 'some', 'b' => 'value')
210
+ }
211
+ assert_equal ['value'], JsonPath.new('$.foo.b').on(object)
212
+ end
213
+
214
+ def test_works_on_non_hash_with_filters
215
+ klass = Struct.new(:a, :b)
216
+ first_object = klass.new('some', 'value')
217
+ second_object = klass.new('next', 'other value')
218
+
219
+ assert_equal ['other value'], JsonPath.new('$[?(@.a == "next")].b').on([first_object, second_object])
220
+ end
221
+
222
+ def test_works_on_hash_with_summary
223
+ object = {
224
+ "foo" => [{
225
+ "a" => "some",
226
+ "b" => "value"
227
+ }]
228
+ }
229
+ assert_equal [{ "b" => "value" }], JsonPath.new("$.foo[*](b)").on(object)
230
+ end
231
+
232
+ def test_works_on_non_hash_with_summary
233
+ klass = Struct.new(:a, :b)
234
+ object = {
235
+ "foo" => [klass.new("some", "value")]
236
+ }
237
+ assert_equal [{ "b" => "value" }], JsonPath.new("$.foo[*](b)").on(object)
238
+ end
239
+
240
+ def test_recognize_array_with_evald_index
241
+ assert_equal [@object['store']['book'][2]], JsonPath.new('$..book[(@.length-5)]').on(@object)
242
+ end
243
+
244
+ def test_use_first
245
+ assert_equal @object['store']['book'][2], JsonPath.new('$..book[(@.length-5)]').first(@object)
246
+ end
247
+
248
+ def test_counting
249
+ assert_equal 61, JsonPath.new('$..*').on(@object).to_a.size
250
+ end
251
+
252
+ def test_space_in_path
253
+ assert_equal ['e'], JsonPath.new("$.'c d'").on('a' => 'a', 'b' => 'b', 'c d' => 'e')
254
+ end
255
+
256
+ def test_class_method
257
+ assert_equal JsonPath.new('$..author').on(@object), JsonPath.on(@object, '$..author')
258
+ end
259
+
260
+ def test_join
261
+ assert_equal JsonPath.new('$.store.book..author').on(@object), JsonPath.new('$.store').join('book..author').on(@object)
262
+ end
263
+
264
+ def test_gsub
265
+ @object2['store']['bicycle']['price'] += 10
266
+ @object2['store']['book'][0]['price'] += 10
267
+ @object2['store']['book'][1]['price'] += 10
268
+ @object2['store']['book'][2]['price'] += 10
269
+ @object2['store']['book'][3]['price'] += 10
270
+ assert_equal @object2, JsonPath.for(@object).gsub('$..price') { |p| p + 10 }.to_hash
271
+ end
272
+
273
+ def test_gsub!
274
+ JsonPath.for(@object).gsub!('$..price') { |p| p + 10 }
275
+ assert_equal 30, @object['store']['bicycle']['price']
276
+ assert_equal 19, @object['store']['book'][0]['price']
277
+ assert_equal 23, @object['store']['book'][1]['price']
278
+ assert_equal 19, @object['store']['book'][2]['price']
279
+ assert_equal 33, @object['store']['book'][3]['price']
280
+ end
281
+
282
+ def test_weird_gsub!
283
+ h = { 'hi' => 'there' }
284
+ JsonPath.for(@object).gsub!('$.*') { |_| h }
285
+ assert_equal h, @object
286
+ end
287
+
288
+ def test_gsub_to_false!
289
+ h = { 'hi' => 'there' }
290
+ h2 = { 'hi' => false }
291
+ assert_equal h2, JsonPath.for(h).gsub!('$.hi') { |_| false }.to_hash
292
+ end
293
+
294
+ def test_where_selector
295
+ JsonPath.for(@object).gsub!('$..book.price[?(@ > 20)]') { |p| p + 10 }
296
+ end
297
+
298
+ def test_compact
299
+ h = { 'hi' => 'there', 'you' => nil }
300
+ JsonPath.for(h).compact!
301
+ assert_equal({ 'hi' => 'there' }, h)
302
+ end
303
+
304
+ def test_delete
305
+ h = { 'hi' => 'there', 'you' => nil }
306
+ JsonPath.for(h).delete!('*.hi')
307
+ assert_equal({ 'you' => nil }, h)
308
+ end
309
+
310
+ def test_delete_2
311
+ json = { 'store' => {
312
+ 'book' => [
313
+ { 'category' => 'reference',
314
+ 'author' => 'Nigel Rees',
315
+ 'title' => 'Sayings of the Century',
316
+ 'price' => 9,
317
+ 'tags' => %w[asdf asdf2] },
318
+ { 'category' => 'fiction',
319
+ 'author' => 'Evelyn Waugh',
320
+ 'title' => 'Sword of Honour',
321
+ 'price' => 13 },
322
+ { 'category' => 'fiction',
323
+ 'author' => 'Aasdf',
324
+ 'title' => 'Aaasdf2',
325
+ 'price' => 1 }
326
+ ]
327
+ } }
328
+ json_deleted = { 'store' => {
329
+ 'book' => [
330
+ { 'category' => 'fiction',
331
+ 'author' => 'Evelyn Waugh',
332
+ 'title' => 'Sword of Honour',
333
+ 'price' => 13 },
334
+ { 'category' => 'fiction',
335
+ 'author' => 'Aasdf',
336
+ 'title' => 'Aaasdf2',
337
+ 'price' => 1 }
338
+ ]
339
+ } }
340
+ assert_equal(json_deleted, JsonPath.for(json).delete("$..store.book[?(@.category == 'reference')]").obj)
341
+ end
342
+
343
+ def test_delete_3
344
+ json = { 'store' => {
345
+ 'book' => [
346
+ { 'category' => 'reference',
347
+ 'author' => 'Nigel Rees',
348
+ 'title' => 'Sayings of the Century',
349
+ 'price' => 9,
350
+ 'tags' => %w[asdf asdf2],
351
+ 'this' => {
352
+ 'delete_me' => [
353
+ 'no' => 'do not'
354
+ ]
355
+ } },
356
+ { 'category' => 'fiction',
357
+ 'author' => 'Evelyn Waugh',
358
+ 'title' => 'Sword of Honour',
359
+ 'price' => 13 },
360
+ { 'category' => 'fiction',
361
+ 'author' => 'Aasdf',
362
+ 'title' => 'Aaasdf2',
363
+ 'price' => 1 }
364
+ ]
365
+ } }
366
+ json_deleted = { 'store' => {
367
+ 'book' => [
368
+ { 'category' => 'reference',
369
+ 'author' => 'Nigel Rees',
370
+ 'title' => 'Sayings of the Century',
371
+ 'price' => 9,
372
+ 'tags' => %w[asdf asdf2],
373
+ 'this' => {} },
374
+ { 'category' => 'fiction',
375
+ 'author' => 'Evelyn Waugh',
376
+ 'title' => 'Sword of Honour',
377
+ 'price' => 13 },
378
+ { 'category' => 'fiction',
379
+ 'author' => 'Aasdf',
380
+ 'title' => 'Aaasdf2',
381
+ 'price' => 1 }
382
+ ]
383
+ } }
384
+ assert_equal(json_deleted, JsonPath.for(json).delete('$..store.book..delete_me').obj)
385
+ end
386
+
387
+ def test_delete_for_array
388
+ before = JsonPath.on(@object, '$..store.book[1]')
389
+ JsonPath.for(@object).delete!('$..store.book[0]')
390
+ after = JsonPath.on(@object, '$..store.book[0]')
391
+ assert_equal(after, before, 'Before is the second element. After should have been equal to the next element after delete.')
392
+ end
393
+
394
+ def test_at_sign_in_json_element
395
+ data =
396
+ { '@colors' =>
397
+ [{ '@r' => 255, '@g' => 0, '@b' => 0 },
398
+ { '@r' => 0, '@g' => 255, '@b' => 0 },
399
+ { '@r' => 0, '@g' => 0, '@b' => 255 }] }
400
+
401
+ assert_equal [255, 0, 0], JsonPath.on(data, '$..@r')
402
+ end
403
+
404
+ def test_wildcard
405
+ assert_equal @object['store']['book'].collect { |e| e['price'] }.compact, JsonPath.on(@object, '$..book[*].price')
406
+ end
407
+
408
+ def test_wildcard_on_intermediary_element
409
+ assert_equal [1], JsonPath.on({ 'a' => { 'b' => { 'c' => 1 } } }, '$.a..c')
410
+ end
411
+
412
+ def test_wildcard_on_intermediary_element_v2
413
+ assert_equal [1], JsonPath.on({ 'a' => { 'b' => { 'd' => { 'c' => 1 } } } }, '$.a..c')
414
+ end
415
+
416
+ def test_wildcard_on_intermediary_element_v3
417
+ assert_equal [1], JsonPath.on({ 'a' => { 'b' => { 'd' => { 'c' => 1 } } } }, '$.a.*..c')
418
+ end
419
+
420
+ def test_wildcard_on_intermediary_element_v4
421
+ assert_equal [1], JsonPath.on({ 'a' => { 'b' => { 'd' => { 'c' => 1 } } } }, '$.a.*..c')
422
+ end
423
+
424
+ def test_wildcard_on_intermediary_element_v5
425
+ assert_equal [1], JsonPath.on({ 'a' => { 'b' => { 'c' => 1 } } }, '$.a.*.c')
426
+ end
427
+
428
+ def test_wildcard_on_intermediary_element_v6
429
+ assert_equal ['red'], JsonPath.new('$.store.*.color').on(@object)
430
+ end
431
+
432
+ def test_wildcard_empty_array
433
+ object = @object.merge('bicycle' => { 'tire' => [] })
434
+ assert_equal [], JsonPath.on(object, '$..bicycle.tire[*]')
435
+ end
436
+
437
+ def test_support_filter_by_array_childnode_value
438
+ assert_equal [@object['store']['book'][3]], JsonPath.new('$..book[?(@.price > 20)]').on(@object)
439
+ end
440
+
441
+ def test_support_filter_by_childnode_value_with_inconsistent_children
442
+ @object['store']['book'][0] = 'string_instead_of_object'
443
+ assert_equal [@object['store']['book'][3]], JsonPath.new('$..book[?(@.price > 20)]').on(@object)
444
+ end
445
+
446
+ def test_support_filter_by_childnode_value_and_select_child_key
447
+ assert_equal [23], JsonPath.new('$..book[?(@.price > 20)].price').on(@object)
448
+ end
449
+
450
+ def test_support_filter_by_childnode_value_over_childnode_and_select_child_key
451
+ assert_equal ['Osennie Vizity'], JsonPath.new('$..book[?(@.written.year == 1996)].title').on(@object)
452
+ end
453
+
454
+ def test_support_filter_by_object_childnode_value
455
+ data = {
456
+ 'data' => {
457
+ 'type' => 'users',
458
+ 'id' => '123'
459
+ }
460
+ }
461
+ assert_equal [{ 'type' => 'users', 'id' => '123' }], JsonPath.new("$.data[?(@.type == 'users')]").on(data)
462
+ assert_equal [], JsonPath.new("$.[?(@.type == 'admins')]").on(data)
463
+ end
464
+
465
+ def test_support_at_sign_in_member_names
466
+ assert_equal [@object['store']['@id']], JsonPath.new('$.store.@id').on(@object)
467
+ end
468
+
469
+ def test_support_dollar_sign_in_member_names
470
+ assert_equal [@object['store']['$meta-data']],
471
+ JsonPath.new('$.store.$meta-data').on(@object)
472
+ end
473
+
474
+ def test_support_underscore_in_member_names
475
+ assert_equal [@object['store']['_links']],
476
+ JsonPath.new('$.store._links').on(@object)
477
+ end
478
+
479
+ def test_support_for_umlauts_in_member_names
480
+ assert_equal [@object['store']['Übermorgen']],
481
+ JsonPath.new('$.store.Übermorgen').on(@object)
482
+ end
483
+
484
+ def test_support_for_spaces_in_member_name
485
+ assert_equal [@object['store']['Title Case']],
486
+ JsonPath.new('$.store.Title Case').on(@object)
487
+ end
488
+
489
+ def test_dig_return_string
490
+ assert_equal ['asdf'], JsonPath.new("$.store.book..tags[?(@ == 'asdf')]").on(@object)
491
+ assert_equal [], JsonPath.new("$.store.book..tags[?(@ == 'not_asdf')]").on(@object)
492
+ end
493
+
494
+ def test_slash_in_value
495
+ data = {
496
+ 'data' => [{
497
+ 'type' => 'mps/awesome'
498
+ }, {
499
+ 'type' => 'not'
500
+ }]
501
+ }
502
+ assert_equal [{ 'type' => 'mps/awesome' }], JsonPath.new('$.data[?(@.type == "mps/awesome")]').on(data)
503
+ end
504
+
505
+ def test_floating_point_with_precision_marker
506
+ data = {
507
+ 'data' => {
508
+ 'type' => 0.00001
509
+ }
510
+ }
511
+ assert_equal [{ 'type' => 0.00001 }], JsonPath.new('$.data[?(@.type == 0.00001)]').on(data)
512
+ end
513
+
514
+ def test_digits_only_string
515
+ data = {
516
+ 'foo' => {
517
+ 'type' => 'users',
518
+ 'id' => '123'
519
+ }
520
+ }
521
+ assert_equal([{ 'type' => 'users', 'id' => '123' }], JsonPath.new("$.foo[?(@.id == '123')]").on(data))
522
+ end
523
+
524
+ def test_digits_only_string_in_array
525
+ data = {
526
+ 'foo' => [{
527
+ 'type' => 'users',
528
+ 'id' => '123'
529
+ }, {
530
+ 'type' => 'users',
531
+ 'id' => '321'
532
+ }]
533
+ }
534
+ assert_equal([{ 'type' => 'users', 'id' => '123' }], JsonPath.new("$.foo[?(@.id == '123')]").on(data))
535
+ end
536
+
537
+ def test_at_in_filter
538
+ jsonld = {
539
+ 'mentions' => [
540
+ {
541
+ 'name' => 'Delimara Powerplant',
542
+ 'identifier' => 'krzana://took/powerstation/Delimara Powerplant',
543
+ '@type' => 'Place',
544
+ 'geo' => {
545
+ 'latitude' => 35.83020073454,
546
+ 'longitude' => 14.55602645874
547
+ }
548
+ }
549
+ ]
550
+ }
551
+ assert_equal(['Place'], JsonPath.new("$..mentions[?(@['@type'] == 'Place')].@type").on(jsonld))
552
+ end
553
+
554
+ def test_dollar_in_filter
555
+ jsonld = {
556
+ 'mentions' => [
557
+ {
558
+ 'name' => 'Delimara Powerplant',
559
+ 'identifier' => 'krzana://took/powerstation/Delimara Powerplant',
560
+ '$type' => 'Place',
561
+ 'geo' => {
562
+ 'latitude' => 35.83020073454,
563
+ 'longitude' => 14.55602645874
564
+ }
565
+ }
566
+ ]
567
+ }
568
+ assert_equal(['Place'], JsonPath.new("$..mentions[?(@['$type'] == 'Place')].$type").on(jsonld))
569
+ end
570
+
571
+ def test_underscore_in_filter
572
+ jsonld = {
573
+ 'attributes' => [
574
+ {
575
+ 'store' => [
576
+ { 'with' => 'urn' },
577
+ { 'with_underscore' => 'urn:1' }
578
+ ]
579
+ }
580
+ ]
581
+ }
582
+ assert_equal(['urn:1'], JsonPath.new("$.attributes..store[?(@['with_underscore'] == 'urn:1')].with_underscore").on(jsonld))
583
+ end
584
+
585
+ def test_space_in_filter
586
+ jsonld = {
587
+ 'store' => [
588
+ { 'withoutspace' => 'urn' },
589
+ { 'with space' => 'urn:1' }
590
+ ]
591
+ }
592
+ assert_equal([{ 'with space' => 'urn:1' }], JsonPath.new("$.store[?(@['with space'])]").on(jsonld))
593
+ end
594
+
595
+ def test_at_in_value
596
+ jsonld = {
597
+ 'mentions' =>
598
+ {
599
+ 'name' => 'Delimara Powerplant',
600
+ 'identifier' => 'krzana://took/powerstation/Delimara Powerplant',
601
+ 'type' => '@Place',
602
+ 'geo' => {
603
+ 'latitude' => 35.83020073454,
604
+ 'longitude' => 14.55602645874
605
+ }
606
+ }
607
+ }
608
+ assert_equal(['@Place'], JsonPath.new("$..mentions.type[?(@ == '@Place')]").on(jsonld))
609
+ end
610
+
611
+ def test_parens_in_value
612
+ data = {
613
+ 'data' => {
614
+ 'number' => '(492) 080-3961'
615
+ }
616
+ }
617
+ assert_equal [{ 'number' => '(492) 080-3961' }], JsonPath.new("$.data[?(@.number == '(492) 080-3961')]").on(data)
618
+ end
619
+
620
+ def test_boolean_parameter_value
621
+ data = {
622
+ 'data' => [{
623
+ 'isTrue' => true,
624
+ 'name' => 'testname1'
625
+ }, {
626
+ 'isTrue' => false,
627
+ 'name' => 'testname2'
628
+ }]
629
+ }
630
+
631
+ # These queries should be equivalent
632
+ expected = [{ 'isTrue' => true, 'name' => 'testname1' }]
633
+ assert_equal expected, JsonPath.new('$.data[?(@.isTrue)]').on(data)
634
+ assert_equal expected, JsonPath.new('$.data[?(@.isTrue==true)]').on(data)
635
+ assert_equal expected, JsonPath.new('$.data[?(@.isTrue == true)]').on(data)
636
+
637
+ # These queries should be equivalent
638
+ expected = [{ 'isTrue' => false, 'name' => 'testname2' }]
639
+ assert_equal expected, JsonPath.new('$.data[?(@.isTrue != true)]').on(data)
640
+ assert_equal expected, JsonPath.new('$.data[?(@.isTrue!=true)]').on(data)
641
+ assert_equal expected, JsonPath.new('$.data[?(@.isTrue==false)]').on(data)
642
+ end
643
+
644
+ def test_and_operator_with_boolean_parameter_value
645
+ data = {
646
+ 'data' => [{
647
+ 'hasProperty1' => true,
648
+ 'hasProperty2' => false,
649
+ 'name' => 'testname1'
650
+ }, {
651
+ 'hasProperty1' => false,
652
+ 'hasProperty2' => true,
653
+ 'name' => 'testname2'
654
+ }, {
655
+ 'hasProperty1' => true,
656
+ 'hasProperty2' => true,
657
+ 'name' => 'testname3'
658
+ }]
659
+ }
660
+ assert_equal ['testname3'], JsonPath.new('$.data[?(@.hasProperty1 && @.hasProperty2)].name').on(data)
661
+ end
662
+
663
+ def test_regex_simple
664
+ assert_equal %w[asdf asdf2], JsonPath.new('$.store.book..tags[?(@ =~ /asdf/)]').on(@object)
665
+ assert_equal %w[asdf asdf2], JsonPath.new('$.store.book..tags[?(@=~/asdf/)]').on(@object)
666
+ end
667
+
668
+ def test_regex_simple_miss
669
+ assert_equal [], JsonPath.new('$.store.book..tags[?(@ =~ /wut/)]').on(@object)
670
+ end
671
+
672
+ def test_regex_r
673
+ assert_equal %w[asdf asdf2], JsonPath.new('$.store.book..tags[?(@ =~ %r{asdf})]').on(@object)
674
+ end
675
+
676
+ def test_regex_flags
677
+ assert_equal [
678
+ @object['store']['book'][2],
679
+ @object['store']['book'][4],
680
+ @object['store']['book'][5],
681
+ @object['store']['book'][6]
682
+ ], JsonPath.new('$..book[?(@.author =~ /herman|lukyanenko/i)]').on(@object)
683
+ end
684
+
685
+ def test_regex_error
686
+ assert_raises ArgumentError do
687
+ JsonPath.new('$.store.book..tags[?(@ =~ asdf)]').on(@object)
688
+ end
689
+ end
690
+
691
+ def test_regression_1
692
+ json = {
693
+ ok: true,
694
+ channels: [
695
+ {
696
+ id: 'C09C5GYHF',
697
+ name: 'general'
698
+ },
699
+ {
700
+ id: 'C09C598QL',
701
+ name: 'random'
702
+ }
703
+ ]
704
+ }.to_json
705
+
706
+ assert_equal 'C09C5GYHF', JsonPath.on(json, "$..channels[?(@.name == 'general')].id")[0]
707
+ end
708
+
709
+ def test_regression_2
710
+ json = {
711
+ ok: true,
712
+ channels: [
713
+ {
714
+ id: 'C09C5GYHF',
715
+ name: 'general',
716
+ is_archived: false
717
+ },
718
+ {
719
+ id: 'C09C598QL',
720
+ name: 'random',
721
+ is_archived: true
722
+ }
723
+ ]
724
+ }.to_json
725
+
726
+ assert_equal 'C09C5GYHF', JsonPath.on(json, '$..channels[?(@.is_archived == false)].id')[0]
727
+ end
728
+
729
+ def test_regression_3
730
+ json = {
731
+ ok: true,
732
+ channels: [
733
+ {
734
+ id: 'C09C5GYHF',
735
+ name: 'general',
736
+ is_archived: false
737
+ },
738
+ {
739
+ id: 'C09C598QL',
740
+ name: 'random',
741
+ is_archived: true
742
+ }
743
+ ]
744
+ }.to_json
745
+
746
+ assert_equal 'C09C598QL', JsonPath.on(json, '$..channels[?(@.is_archived)].id')[0]
747
+ end
748
+
749
+ def test_regression_4
750
+ json = {
751
+ ok: true,
752
+ channels: [
753
+ {
754
+ id: 'C09C5GYHF',
755
+ name: 'general',
756
+ is_archived: false
757
+ },
758
+ {
759
+ id: 'C09C598QL',
760
+ name: 'random',
761
+ is_archived: true
762
+ }
763
+ ]
764
+ }.to_json
765
+
766
+ assert_equal ['C09C5GYHF'], JsonPath.on(json, "$..channels[?(@.name == 'general')].id")
767
+ end
768
+
769
+ def test_regression_5
770
+ json = {
771
+ ok: true,
772
+ channels: [
773
+ {
774
+ id: 'C09C5GYHF',
775
+ name: 'general',
776
+ is_archived: 'false'
777
+ },
778
+ {
779
+ id: 'C09C598QL',
780
+ name: 'random',
781
+ is_archived: true
782
+ }
783
+ ]
784
+ }.to_json
785
+
786
+ assert_equal 'C09C5GYHF', JsonPath.on(json, "$..channels[?(@.is_archived == 'false')].id")[0]
787
+ end
788
+
789
+ def test_quote
790
+ json = {
791
+ channels: [
792
+ {
793
+ name: "King's Speech"
794
+ }
795
+ ]
796
+ }.to_json
797
+
798
+ assert_equal [{ 'name' => "King\'s Speech" }], JsonPath.on(json, "$..channels[?(@.name == 'King\'s Speech')]")
799
+ end
800
+
801
+ def test_curly_brackets
802
+ data = {
803
+ '{data}' => 'data'
804
+ }
805
+ assert_equal ['data'], JsonPath.new('$.{data}').on(data)
806
+ end
807
+
808
+ def test_symbolize
809
+ data = '
810
+ {
811
+ "store": {
812
+ "bicycle": {
813
+ "price": 19.95,
814
+ "color": "red"
815
+ },
816
+ "book": [
817
+ {
818
+ "price": 8.95,
819
+ "category": "reference",
820
+ "title": "Sayings of the Century",
821
+ "author": "Nigel Rees"
822
+ },
823
+ {
824
+ "price": 12.99,
825
+ "category": "fiction",
826
+ "title": "Sword of Honour",
827
+ "author": "Evelyn Waugh"
828
+ },
829
+ {
830
+ "price": 8.99,
831
+ "category": "fiction",
832
+ "isbn": "0-553-21311-3",
833
+ "title": "Moby Dick",
834
+ "author": "Herman Melville",
835
+ "color": "blue"
836
+ },
837
+ {
838
+ "price": 22.99,
839
+ "category": "fiction",
840
+ "isbn": "0-395-19395-8",
841
+ "title": "The Lord of the Rings",
842
+ "author": "Tolkien"
843
+ }
844
+ ]
845
+ }
846
+ }
847
+ '
848
+ assert_equal [{ price: 8.95, category: 'reference', title: 'Sayings of the Century', author: 'Nigel Rees' }, { price: 8.99, category: 'fiction', isbn: '0-553-21311-3', title: 'Moby Dick', author: 'Herman Melville', color: 'blue' }], JsonPath.new('$..book[::2]').on(data, symbolize_keys: true)
849
+ end
850
+
851
+ def test_changed
852
+ json =
853
+ {
854
+ 'snapshot' => {
855
+ 'objects' => {
856
+ 'whatever' => [
857
+ {
858
+ 'column' => {
859
+ 'name' => 'ASSOCIATE_FLAG',
860
+ 'nullable' => true
861
+ }
862
+ },
863
+ {
864
+ 'column' => {
865
+ 'name' => 'AUTHOR',
866
+ 'nullable' => false
867
+ }
868
+ }
869
+ ]
870
+ }
871
+ }
872
+ }
873
+ assert_equal true, JsonPath.on(json, "$..column[?(@.name == 'ASSOCIATE_FLAG')].nullable")[0]
874
+ end
875
+
876
+ def test_another
877
+ json = {
878
+ initial: true,
879
+ not: true
880
+ }.to_json
881
+ assert_equal [{ 'initial' => true, 'not' => true }], JsonPath.on(json, '$.[?(@.initial == true)]')
882
+ json = {
883
+ initial: false,
884
+ not: true
885
+ }.to_json
886
+ assert_equal [], JsonPath.on(json, '$.initial[?(@)]')
887
+ assert_equal [], JsonPath.on(json, '$.[?(@.initial == true)]')
888
+ assert_equal [{ 'initial' => false, 'not' => true }], JsonPath.on(json, '$.[?(@.initial == false)]')
889
+ json = {
890
+ initial: 'false',
891
+ not: true
892
+ }.to_json
893
+ assert_equal [{ 'initial' => 'false', 'not' => true }], JsonPath.on(json, "$.[?(@.initial == 'false')]")
894
+ assert_equal [], JsonPath.on(json, '$.[?(@.initial == false)]')
895
+ end
896
+
897
+ def test_hanging
898
+ json = { initial: true }.to_json
899
+ success_path = '$.initial'
900
+ assert_equal [true], JsonPath.on(json, success_path)
901
+ broken_path = "$.initial\n"
902
+ assert_equal [true], JsonPath.on(json, broken_path)
903
+ end
904
+
905
+ def test_complex_nested_grouping
906
+ path = "$..book[?((@['author'] == 'Evelyn Waugh' || @['author'] == 'Herman Melville') && (@['price'] == 33 || @['price'] == 9))]"
907
+ assert_equal [@object['store']['book'][2]], JsonPath.new(path).on(@object)
908
+ end
909
+
910
+ def test_nested_with_unknown_key
911
+ path = "$..[?(@.price == 9 || @.price == 33)].title"
912
+ assert_equal ["Sayings of the Century", "Moby Dick", "Sayings of the Century", "Moby Dick"], JsonPath.new(path).on(@object)
913
+ end
914
+
915
+ def test_nested_with_unknown_key_filtered_array
916
+ path = "$..[?(@['price'] == 9 || @['price'] == 33)].title"
917
+ assert_equal ["Sayings of the Century", "Moby Dick", "Sayings of the Century", "Moby Dick"], JsonPath.new(path).on(@object)
918
+ end
919
+
920
+ def test_runtime_error_frozen_string
921
+ skip('in ruby version below 2.2.0 this error is not raised') if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2.0') || Gem::Version.new(RUBY_VERSION) > Gem::Version::new('2.6')
922
+ json = '
923
+ {
924
+ "test": "something"
925
+ }
926
+ '.to_json
927
+ assert_raises(ArgumentError, "RuntimeError: character '|' not supported in query") do
928
+ JsonPath.on(json, '$.description|title')
929
+ end
930
+ end
931
+
932
+ def test_delete_more_items
933
+ a = { 'itemList' =>
934
+ [{ 'alfa' => 'beta1' },
935
+ { 'alfa' => 'beta2' },
936
+ { 'alfa' => 'beta3' },
937
+ { 'alfa' => 'beta4' },
938
+ { 'alfa' => 'beta5' },
939
+ { 'alfa' => 'beta6' },
940
+ { 'alfa' => 'beta7' },
941
+ { 'alfa' => 'beta8' },
942
+ { 'alfa' => 'beta9' },
943
+ { 'alfa' => 'beta10' },
944
+ { 'alfa' => 'beta11' },
945
+ { 'alfa' => 'beta12' }] }
946
+ expected = { 'itemList' => [{ 'alfa' => 'beta1' }] }
947
+ assert_equal expected, JsonPath.for(a.to_json).delete('$.itemList[1:12:1]').to_hash
948
+ end
949
+
950
+ def test_delete_more_items_with_stepping
951
+ a = { 'itemList' =>
952
+ [{ 'alfa' => 'beta1' },
953
+ { 'alfa' => 'beta2' },
954
+ { 'alfa' => 'beta3' },
955
+ { 'alfa' => 'beta4' },
956
+ { 'alfa' => 'beta5' },
957
+ { 'alfa' => 'beta6' },
958
+ { 'alfa' => 'beta7' },
959
+ { 'alfa' => 'beta8' },
960
+ { 'alfa' => 'beta9' },
961
+ { 'alfa' => 'beta10' },
962
+ { 'alfa' => 'beta11' },
963
+ { 'alfa' => 'beta12' }] }
964
+ expected = { 'itemList' =>
965
+ [{ 'alfa' => 'beta1' },
966
+ { 'alfa' => 'beta3' },
967
+ { 'alfa' => 'beta5' },
968
+ { 'alfa' => 'beta7' },
969
+ { 'alfa' => 'beta8' },
970
+ { 'alfa' => 'beta9' },
971
+ { 'alfa' => 'beta10' },
972
+ { 'alfa' => 'beta11' },
973
+ { 'alfa' => 'beta12' }] }
974
+ assert_equal expected, JsonPath.for(a.to_json).delete('$.itemList[1:6:2]').to_hash
975
+ end
976
+
977
+ def test_nested_values
978
+ json = '
979
+ {
980
+ "phoneNumbers": [
981
+ [{
982
+ "type" : "iPhone",
983
+ "number": "0123-4567-8888"
984
+ }],
985
+ [{
986
+ "type" : "home",
987
+ "number": "0123-4567-8910"
988
+ }]
989
+ ]
990
+ }
991
+ '.to_json
992
+ assert_equal [[{ 'type' => 'home', 'number' => '0123-4567-8910' }]], JsonPath.on(json, "$.phoneNumbers[?(@[0].type == 'home')]")
993
+ assert_equal [], JsonPath.on(json, "$.phoneNumbers[?(@[2].type == 'home')]")
994
+ json = '
995
+ {
996
+ "phoneNumbers":
997
+ {
998
+ "type" : "iPhone",
999
+ "number": "0123-4567-8888"
1000
+ }
1001
+ }
1002
+ '.to_json
1003
+ assert_equal [], JsonPath.on(json, "$.phoneNumbers[?(@[0].type == 'home')]")
1004
+ end
1005
+
1006
+ def test_selecting_multiple_keys_on_hash
1007
+ json = '
1008
+ {
1009
+ "category": "reference",
1010
+ "author": "Nigel Rees",
1011
+ "title": "Sayings of the Century",
1012
+ "price": 8.95
1013
+ }
1014
+ '.to_json
1015
+ assert_equal [{ 'category' => 'reference', 'author' => 'Nigel Rees' }], JsonPath.on(json, '$.(category,author)')
1016
+ end
1017
+
1018
+ def test_selecting_multiple_keys_on_sub_hash
1019
+ skip("Failing as the semantics of .(x,y) is unclear")
1020
+ json = '
1021
+ {
1022
+ "book": {
1023
+ "category": "reference",
1024
+ "author": "Nigel Rees",
1025
+ "title": "Sayings of the Century",
1026
+ "price": 8.95
1027
+ }
1028
+ }
1029
+ '.to_json
1030
+ assert_equal [{ 'category' => 'reference', 'author' => 'Nigel Rees' }], JsonPath.on(json, '$.book.(category,author)')
1031
+ end
1032
+
1033
+ def test_selecting_multiple_keys_on_array
1034
+ json = '
1035
+ {
1036
+ "store": {
1037
+ "book": [
1038
+ {
1039
+ "category": "reference",
1040
+ "author": "Nigel Rees",
1041
+ "title": "Sayings of the Century",
1042
+ "price": 8.95
1043
+ },
1044
+ {
1045
+ "category": "fiction",
1046
+ "author": "Evelyn Waugh",
1047
+ "title": "Sword of Honour",
1048
+ "price": 12.99
1049
+ }
1050
+ ]
1051
+ }
1052
+ }
1053
+ '.to_json
1054
+
1055
+ assert_equal [{ 'category' => 'reference', 'author' => 'Nigel Rees' }, { 'category' => 'fiction', 'author' => 'Evelyn Waugh' }], JsonPath.on(json, '$.store.book[*](category,author)')
1056
+ end
1057
+
1058
+ def test_selecting_multiple_keys_on_array_with_filter
1059
+ json = '
1060
+ {
1061
+ "store": {
1062
+ "book": [
1063
+ {
1064
+ "category": "reference",
1065
+ "author": "Nigel Rees",
1066
+ "title": "Sayings of the Century",
1067
+ "price": 8.95
1068
+ },
1069
+ {
1070
+ "category": "fiction",
1071
+ "author": "Evelyn Waugh",
1072
+ "title": "Sword of Honour",
1073
+ "price": 12.99
1074
+ }
1075
+ ]
1076
+ }
1077
+ }
1078
+ '.to_json
1079
+
1080
+ assert_equal [{ 'category' => 'reference', 'author' => 'Nigel Rees' }], JsonPath.on(json, "$.store.book[?(@['price'] == 8.95)](category,author)")
1081
+ assert_equal [{ 'category' => 'reference', 'author' => 'Nigel Rees' }], JsonPath.on(json, "$.store.book[?(@['price'] == 8.95)]( category, author )")
1082
+ end
1083
+
1084
+ def test_selecting_multiple_keys_with_filter_with_space_in_catergory
1085
+ json = '
1086
+ {
1087
+ "store": {
1088
+ "book": [
1089
+ {
1090
+ "cate gory": "reference",
1091
+ "author": "Nigel Rees",
1092
+ "title": "Sayings of the Century",
1093
+ "price": 8.95
1094
+ },
1095
+ {
1096
+ "cate gory": "fiction",
1097
+ "author": "Evelyn Waugh",
1098
+ "title": "Sword of Honour",
1099
+ "price": 12.99
1100
+ }
1101
+ ]
1102
+ }
1103
+ }
1104
+ '.to_json
1105
+
1106
+ assert_equal [{ 'cate gory' => 'reference', 'author' => 'Nigel Rees' }], JsonPath.on(json, "$.store.book[?(@['price'] == 8.95)]( cate gory, author )")
1107
+ end
1108
+
1109
+ def test_use_symbol_opt
1110
+ json = {
1111
+ store: {
1112
+ book: [
1113
+ {
1114
+ category: "reference",
1115
+ author: "Nigel Rees",
1116
+ title: "Sayings of the Century",
1117
+ price: 8.95
1118
+ },
1119
+ {
1120
+ category: "fiction",
1121
+ author: "Evelyn Waugh",
1122
+ title: "Sword of Honour",
1123
+ price: 12.99
1124
+ }
1125
+ ]
1126
+ }
1127
+ }
1128
+ on = ->(path){ JsonPath.on(json, path, use_symbols: true) }
1129
+ assert_equal ['reference', 'fiction'], on.("$.store.book[*].category")
1130
+ assert_equal ['reference', 'fiction'], on.("$..category")
1131
+ assert_equal ['reference'], on.("$.store.book[?(@['price'] == 8.95)].category")
1132
+ assert_equal [{'category' => 'reference'}], on.("$.store.book[?(@['price'] == 8.95)](category)")
1133
+ end
1134
+
1135
+ def test_object_method_send
1136
+ j = {height: 5, hash: "some_hash"}.to_json
1137
+ hs = JsonPath.new "$..send"
1138
+ assert_equal([], hs.on(j))
1139
+ hs = JsonPath.new "$..hash"
1140
+ assert_equal(["some_hash"], hs.on(j))
1141
+ hs = JsonPath.new "$..send"
1142
+ assert_equal([], hs.on(j))
1143
+ j = {height: 5, send: "should_still_work"}.to_json
1144
+ hs = JsonPath.new "$..send"
1145
+ assert_equal(['should_still_work'], hs.on(j))
1146
+ end
1147
+
1148
+ def test_index_access_by_number
1149
+ data = {
1150
+ '1': 'foo'
1151
+ }
1152
+ assert_equal ['foo'], JsonPath.new('$.1').on(data.to_json)
1153
+ end
1154
+
1155
+ def test_behavior_on_null_and_missing
1156
+ data = {
1157
+ "foo" => nil,
1158
+ "bar" => {
1159
+ "baz" => nil
1160
+ },
1161
+ "bars" => [
1162
+ { "foo" => 12 },
1163
+ { "foo" => nil },
1164
+ { }
1165
+ ]
1166
+ }
1167
+ assert_equal [nil], JsonPath.new('$.foo').on(data)
1168
+ assert_equal [nil], JsonPath.new('$.bar.baz').on(data)
1169
+ assert_equal [], JsonPath.new('$.baz').on(data)
1170
+ assert_equal [], JsonPath.new('$.bar.foo').on(data)
1171
+ assert_equal [12, nil], JsonPath.new('$.bars[*].foo').on(data)
1172
+ end
1173
+
1174
+ def test_default_path_leaf_to_null_opt
1175
+ data = {
1176
+ "foo" => nil,
1177
+ "bar" => {
1178
+ "baz" => nil
1179
+ },
1180
+ "bars" => [
1181
+ { "foo" => 12 },
1182
+ { "foo" => nil },
1183
+ { }
1184
+ ]
1185
+ }
1186
+ assert_equal [nil], JsonPath.new('$.foo', default_path_leaf_to_null: true).on(data)
1187
+ assert_equal [nil], JsonPath.new('$.bar.baz', default_path_leaf_to_null: true).on(data)
1188
+ assert_equal [nil], JsonPath.new('$.baz', default_path_leaf_to_null: true).on(data)
1189
+ assert_equal [nil], JsonPath.new('$.bar.foo', default_path_leaf_to_null: true).on(data)
1190
+ assert_equal [12, nil, nil], JsonPath.new('$.bars[*].foo', default_path_leaf_to_null: true).on(data)
1191
+ end
1192
+
1193
+ def test_raise_max_nesting_error
1194
+ json = {
1195
+ a: {
1196
+ b: {
1197
+ c: {
1198
+ }
1199
+ }
1200
+ }
1201
+ }.to_json
1202
+
1203
+ assert_raises(MultiJson::ParseError) { JsonPath.new('$.a', max_nesting: 1).on(json) }
1204
+ end
1205
+
1206
+ def test_linefeed_in_path_error
1207
+ assert_raises(ArgumentError) { JsonPath.new("$.store\n.book") }
1208
+ end
1209
+
1210
+ def test_with_max_nesting_false
1211
+ json = {
1212
+ a: {
1213
+ b: {
1214
+ c: {
1215
+ }
1216
+ }
1217
+ }
1218
+ }.to_json
1219
+
1220
+ assert_equal [{}], JsonPath.new('$.a.b.c', max_nesting: false).on(json)
1221
+ end
1222
+
1223
+ def test_initialize_with_max_nesting_exceeding_limit
1224
+ json = {
1225
+ a: {
1226
+ b: {
1227
+ c: {
1228
+ }
1229
+ }
1230
+ }
1231
+ }.to_json
1232
+
1233
+ json_obj = JsonPath.new('$.a.b.c', max_nesting: 105)
1234
+ assert_equal [{}], json_obj.on(json)
1235
+ assert_equal false, json_obj.instance_variable_get(:@opts)[:max_nesting]
1236
+ end
1237
+
1238
+ def test_initialize_without_max_nesting_exceeding_limit
1239
+ json_obj = JsonPath.new('$.a.b.c', max_nesting: 90)
1240
+ assert_equal 90, json_obj.instance_variable_get(:@opts)[:max_nesting]
1241
+ end
1242
+
1243
+ def test_initialize_with_max_nesting_false_limit
1244
+ json_obj = JsonPath.new('$.a.b.c', max_nesting: false)
1245
+ assert_equal false, json_obj.instance_variable_get(:@opts)[:max_nesting]
1246
+ end
1247
+
1248
+ def example_object
1249
+ { 'store' => {
1250
+ 'book' => [
1251
+ { 'category' => 'reference',
1252
+ 'author' => 'Nigel Rees',
1253
+ 'title' => 'Sayings of the Century',
1254
+ 'price' => 9,
1255
+ 'tags' => %w[asdf asdf2],
1256
+ 'year published' => 1999 },
1257
+ { 'category' => 'fiction',
1258
+ 'author' => 'Evelyn Waugh',
1259
+ 'title' => 'Sword of Honour',
1260
+ 'price' => 13,
1261
+ 'year published' => 1952 },
1262
+ { 'category' => 'fiction',
1263
+ 'author' => 'Herman Melville',
1264
+ 'title' => 'Moby Dick',
1265
+ 'isbn' => '0-553-21311-3',
1266
+ 'price' => 9 },
1267
+ { 'category' => 'fiction',
1268
+ 'author' => 'J. R. R. Tolkien',
1269
+ 'title' => 'The Lord of the Rings',
1270
+ 'isbn' => '0-395-19395-8',
1271
+ 'price' => 23 },
1272
+ { 'category' => 'russian_fiction',
1273
+ 'author' => 'Lukyanenko',
1274
+ 'title' => 'Imperatory Illuziy',
1275
+ 'written' => {
1276
+ 'year' => 1995
1277
+ } },
1278
+ { 'category' => 'russian_fiction',
1279
+ 'author' => 'Lukyanenko',
1280
+ 'title' => 'Osennie Vizity',
1281
+ 'written' => {
1282
+ 'year' => 1996
1283
+ } },
1284
+ { 'category' => 'russian_fiction',
1285
+ 'author' => 'Lukyanenko',
1286
+ 'title' => 'Ne vremya dlya drakonov',
1287
+ 'written' => {
1288
+ 'year' => 1997
1289
+ } }
1290
+ ],
1291
+ 'bicycle' => {
1292
+ 'color' => 'red',
1293
+ 'price' => 20,
1294
+ 'catalogue_number' => 123_45,
1295
+ 'single-speed' => 'no',
1296
+ '2seater' => 'yes',
1297
+ 'make:model' => 'Zippy Sweetwheeler'
1298
+ },
1299
+ '@id' => 'http://example.org/store/42',
1300
+ '$meta-data' => 'whatevs',
1301
+ 'Übermorgen' => 'The day after tomorrow',
1302
+ 'Title Case' => 'A title case string',
1303
+ '_links' => { 'self' => {} }
1304
+ } }
1305
+ end
1306
+
1307
+ def test_fetch_all_path
1308
+ data = {
1309
+ "foo" => nil,
1310
+ "bar" => {
1311
+ "baz" => nil
1312
+ },
1313
+ "bars" => [
1314
+ { "foo" => 12 },
1315
+ { "foo" => nil },
1316
+ { }
1317
+ ]
1318
+ }
1319
+ assert_equal ["$", "$.foo", "$.bar", "$.bar.baz", "$.bars", "$.bars[0].foo", "$.bars[0]", "$.bars[1].foo", "$.bars[1]", "$.bars[2]"], JsonPath.fetch_all_path(data)
1320
+ end
1321
+
1322
+
1323
+ def test_extractore_with_dollar_key
1324
+ json = {"test" => {"$" =>"success", "a" => "123"}}
1325
+ assert_equal ["success"], JsonPath.on(json, "$.test.$")
1326
+ assert_equal ["123"], JsonPath.on(json, "$.test.a")
1327
+ end
1328
+
1329
+ def test_symbolize_key
1330
+ data = { "store" => { "book" => [{"category" => "reference"}]}}
1331
+ assert_equal [{"category": "reference"}], JsonPath.new('$..book[0]', symbolize_keys: true).on(data)
1332
+ assert_equal [{"category": "reference"}], JsonPath.new('$..book[0]').on(data, symbolize_keys: true)
1333
+ end
1334
+ end