jmespath 1.5.0 → 1.6.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 +4 -4
- data/VERSION +1 -1
- data/bin/jmespath.rb +12 -0
- data/lib/jmespath/caching_parser.rb +1 -2
- data/lib/jmespath/errors.rb +2 -2
- data/lib/jmespath/lexer.rb +28 -31
- data/lib/jmespath/nodes/and.rb +1 -2
- data/lib/jmespath/nodes/comparator.rb +14 -22
- data/lib/jmespath/nodes/condition.rb +15 -5
- data/lib/jmespath/nodes/current.rb +1 -0
- data/lib/jmespath/nodes/expression.rb +2 -2
- data/lib/jmespath/nodes/field.rb +3 -7
- data/lib/jmespath/nodes/flatten.rb +1 -2
- data/lib/jmespath/nodes/function.rb +64 -68
- data/lib/jmespath/nodes/index.rb +1 -0
- data/lib/jmespath/nodes/literal.rb +2 -1
- data/lib/jmespath/nodes/multi_select_hash.rb +1 -0
- data/lib/jmespath/nodes/multi_select_list.rb +1 -0
- data/lib/jmespath/nodes/not.rb +1 -2
- data/lib/jmespath/nodes/or.rb +1 -0
- data/lib/jmespath/nodes/pipe.rb +1 -0
- data/lib/jmespath/nodes/projection.rb +4 -11
- data/lib/jmespath/nodes/slice.rb +13 -18
- data/lib/jmespath/nodes/subexpression.rb +1 -0
- data/lib/jmespath/nodes.rb +3 -4
- data/lib/jmespath/parser.rb +24 -29
- data/lib/jmespath/runtime.rb +1 -2
- data/lib/jmespath/token.rb +3 -4
- data/lib/jmespath/token_stream.rb +4 -5
- data/lib/jmespath/util.rb +5 -5
- data/lib/jmespath/version.rb +1 -0
- data/lib/jmespath.rb +6 -8
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6dd359b84687e9959f5ceefc730e01783a02c3c3fd32419112c9cc68bac69fe8
|
4
|
+
data.tar.gz: 19078671387ef295d8d00dfdc6d04758be5d54974b0bf7adfad998af8c0427c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 07234d57953b71829d79eeb7862ad7b55b06f96fb6c35ba7b0764ec1339c5b4c6b632b8d3d81ec4a193300e335e371772b54eb91c1092d46eb8ab374afd598b5
|
7
|
+
data.tar.gz: acc8a1daca807053070f8487a76703e45c67da851b3d32753294e67ad67dd7a930ef8f0596ff327c2779aea61b65c2f874ff5bcd4b34df79ba2366d7b6514f43
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.6.2
|
data/bin/jmespath.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
|
+
|
6
|
+
require 'jmespath'
|
7
|
+
require 'json'
|
8
|
+
|
9
|
+
expression = ARGV[0]
|
10
|
+
json = JSON.parse(STDIN.read)
|
11
|
+
|
12
|
+
$stdout.puts(JSON.dump(JMESPath.search(expression, json)))
|
@@ -1,8 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'thread'
|
2
3
|
|
3
4
|
module JMESPath
|
4
5
|
class CachingParser
|
5
|
-
|
6
6
|
def initialize(options = {})
|
7
7
|
@parser = options[:parser] || Parser.new(options)
|
8
8
|
@mutex = Mutex.new
|
@@ -25,6 +25,5 @@ module JMESPath
|
|
25
25
|
@cache[expression] = @parser.parse(expression)
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
29
28
|
end
|
30
29
|
end
|
data/lib/jmespath/errors.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module JMESPath
|
2
4
|
module Errors
|
3
|
-
|
4
5
|
class Error < StandardError; end
|
5
6
|
|
6
7
|
class RuntimeError < Error; end
|
@@ -14,6 +15,5 @@ module JMESPath
|
|
14
15
|
class InvalidArityError < Error; end
|
15
16
|
|
16
17
|
class UnknownFunctionError < Error; end
|
17
|
-
|
18
18
|
end
|
19
19
|
end
|
data/lib/jmespath/lexer.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'json'
|
2
3
|
require 'set'
|
3
4
|
|
4
5
|
module JMESPath
|
5
6
|
# @api private
|
6
7
|
class Lexer
|
7
|
-
|
8
8
|
T_DOT = :dot
|
9
9
|
T_STAR = :star
|
10
10
|
T_COMMA = :comma
|
@@ -134,14 +134,14 @@ module JMESPath
|
|
134
134
|
'w' => STATE_IDENTIFIER,
|
135
135
|
'x' => STATE_IDENTIFIER,
|
136
136
|
'y' => STATE_IDENTIFIER,
|
137
|
-
'z' => STATE_IDENTIFIER
|
138
|
-
}
|
137
|
+
'z' => STATE_IDENTIFIER
|
138
|
+
}.freeze
|
139
139
|
|
140
140
|
VALID_IDENTIFIERS = Set.new(%w(
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
141
|
+
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
|
142
|
+
a b c d e f g h i j k l m n o p q r s t u v w x y z
|
143
|
+
_ 0 1 2 3 4 5 6 7 8 9
|
144
|
+
))
|
145
145
|
|
146
146
|
NUMBERS = Set.new(%w(0 1 2 3 4 5 6 7 8 9))
|
147
147
|
|
@@ -155,13 +155,12 @@ module JMESPath
|
|
155
155
|
'(' => T_LPAREN,
|
156
156
|
')' => T_RPAREN,
|
157
157
|
'{' => T_LBRACE,
|
158
|
-
'}' => T_RBRACE
|
159
|
-
}
|
158
|
+
'}' => T_RBRACE
|
159
|
+
}.freeze
|
160
160
|
|
161
161
|
# @param [String<JMESPath>] expression
|
162
162
|
# @return [Array<Hash>]
|
163
163
|
def tokenize(expression)
|
164
|
-
|
165
164
|
tokens = []
|
166
165
|
chars = CharacterStream.new(expression.chars.to_a)
|
167
166
|
|
@@ -253,7 +252,7 @@ module JMESPath
|
|
253
252
|
tokens << match_or(chars, '&', '&', T_AND, T_EXPREF)
|
254
253
|
when STATE_NOT
|
255
254
|
# consume not equals
|
256
|
-
tokens << match_or(chars, '!', '=', T_COMPARATOR, T_NOT)
|
255
|
+
tokens << match_or(chars, '!', '=', T_COMPARATOR, T_NOT)
|
257
256
|
else
|
258
257
|
# either '<' or '>'
|
259
258
|
# consume less than and greater than
|
@@ -298,12 +297,12 @@ module JMESPath
|
|
298
297
|
# Certain versions of Ruby and of the pure_json gem not support loading
|
299
298
|
# scalar JSON values, such a numbers, booleans, strings, etc. These
|
300
299
|
# simple values must be first wrapped inside a JSON object before calling
|
301
|
-
# `JSON.
|
300
|
+
# `JSON.parse`.
|
302
301
|
#
|
303
302
|
# # works in most JSON versions, raises in some versions
|
304
|
-
# JSON.
|
305
|
-
# JSON.
|
306
|
-
# JSON.
|
303
|
+
# JSON.parse("true")
|
304
|
+
# JSON.parse("123")
|
305
|
+
# JSON.parse("\"abc\"")
|
307
306
|
#
|
308
307
|
# This is an known issue for:
|
309
308
|
#
|
@@ -317,27 +316,25 @@ module JMESPath
|
|
317
316
|
# causes issues in environments that cannot compile the gem. We previously
|
318
317
|
# had a direct dependency on `json_pure`, but this broke with the v2 update.
|
319
318
|
#
|
320
|
-
# This method allows us to detect how the `JSON.
|
319
|
+
# This method allows us to detect how the `JSON.parse` behaves so we know
|
321
320
|
# if we have to wrap scalar JSON values to parse them or not.
|
322
321
|
# @api private
|
323
322
|
def self.requires_wrapping?
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
true
|
328
|
-
end
|
323
|
+
JSON.parse('false')
|
324
|
+
rescue JSON::ParserError
|
325
|
+
true
|
329
326
|
end
|
330
327
|
|
331
328
|
if requires_wrapping?
|
332
329
|
def parse_json(token, quoted = false)
|
333
330
|
begin
|
334
331
|
if quoted
|
335
|
-
token.value = JSON.
|
332
|
+
token.value = JSON.parse("{\"value\":#{token.value}}")['value']
|
336
333
|
else
|
337
334
|
begin
|
338
|
-
token.value = JSON.
|
335
|
+
token.value = JSON.parse("{\"value\":#{token.value}}")['value']
|
339
336
|
rescue
|
340
|
-
token.value = JSON.
|
337
|
+
token.value = JSON.parse(sprintf('{"value":"%s"}', token.value.lstrip))['value']
|
341
338
|
end
|
342
339
|
end
|
343
340
|
rescue JSON::ParserError
|
@@ -349,9 +346,13 @@ module JMESPath
|
|
349
346
|
def parse_json(token, quoted = false)
|
350
347
|
begin
|
351
348
|
if quoted
|
352
|
-
token.value = JSON.
|
349
|
+
token.value = JSON.parse(token.value)
|
353
350
|
else
|
354
|
-
token.value =
|
351
|
+
token.value = begin
|
352
|
+
JSON.parse(token.value)
|
353
|
+
rescue
|
354
|
+
JSON.parse(sprintf('"%s"', token.value.lstrip))
|
355
|
+
end
|
355
356
|
end
|
356
357
|
rescue JSON::ParserError
|
357
358
|
token.type = T_UNKNOWN
|
@@ -361,7 +362,6 @@ module JMESPath
|
|
361
362
|
end
|
362
363
|
|
363
364
|
class CharacterStream
|
364
|
-
|
365
365
|
def initialize(chars)
|
366
366
|
@chars = chars
|
367
367
|
@position = 0
|
@@ -376,10 +376,7 @@ module JMESPath
|
|
376
376
|
@chars[@position]
|
377
377
|
end
|
378
378
|
|
379
|
-
|
380
|
-
@position
|
381
|
-
end
|
382
|
-
|
379
|
+
attr_reader :position
|
383
380
|
end
|
384
381
|
end
|
385
382
|
end
|
data/lib/jmespath/nodes/and.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module JMESPath
|
2
3
|
module Nodes
|
3
4
|
class And < Node
|
4
|
-
|
5
5
|
def initialize(left, right)
|
6
6
|
@left = left
|
7
7
|
@right = right
|
@@ -19,7 +19,6 @@ module JMESPath
|
|
19
19
|
def optimize
|
20
20
|
self.class.new(@left.optimize, @right.optimize)
|
21
21
|
end
|
22
|
-
|
23
22
|
end
|
24
23
|
end
|
25
24
|
end
|
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module JMESPath
|
2
3
|
# @api private
|
3
4
|
module Nodes
|
4
5
|
class Comparator < Node
|
6
|
+
COMPARABLE_TYPES = [Numeric, String].freeze
|
7
|
+
|
5
8
|
attr_reader :left, :right
|
6
9
|
|
7
10
|
def initialize(left, right)
|
@@ -33,13 +36,18 @@ module JMESPath
|
|
33
36
|
|
34
37
|
private
|
35
38
|
|
36
|
-
def check(
|
39
|
+
def check(_left_value, _right_value)
|
37
40
|
nil
|
38
41
|
end
|
42
|
+
|
43
|
+
def comparable?(left_value, right_value)
|
44
|
+
COMPARABLE_TYPES.any? do |type|
|
45
|
+
left_value.is_a?(type) && right_value.is_a?(type)
|
46
|
+
end
|
47
|
+
end
|
39
48
|
end
|
40
49
|
|
41
50
|
module Comparators
|
42
|
-
|
43
51
|
class Eq < Comparator
|
44
52
|
def check(left_value, right_value)
|
45
53
|
Util.as_json(left_value) == Util.as_json(right_value)
|
@@ -54,41 +62,25 @@ module JMESPath
|
|
54
62
|
|
55
63
|
class Gt < Comparator
|
56
64
|
def check(left_value, right_value)
|
57
|
-
if
|
58
|
-
left_value > right_value
|
59
|
-
else
|
60
|
-
nil
|
61
|
-
end
|
65
|
+
left_value > right_value if comparable?(left_value, right_value)
|
62
66
|
end
|
63
67
|
end
|
64
68
|
|
65
69
|
class Gte < Comparator
|
66
70
|
def check(left_value, right_value)
|
67
|
-
if
|
68
|
-
left_value >= right_value
|
69
|
-
else
|
70
|
-
nil
|
71
|
-
end
|
71
|
+
left_value >= right_value if comparable?(left_value, right_value)
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
75
|
class Lt < Comparator
|
76
76
|
def check(left_value, right_value)
|
77
|
-
if
|
78
|
-
left_value < right_value
|
79
|
-
else
|
80
|
-
nil
|
81
|
-
end
|
77
|
+
left_value < right_value if comparable?(left_value, right_value)
|
82
78
|
end
|
83
79
|
end
|
84
80
|
|
85
81
|
class Lte < Comparator
|
86
82
|
def check(left_value, right_value)
|
87
|
-
if
|
88
|
-
left_value <= right_value
|
89
|
-
else
|
90
|
-
nil
|
91
|
-
end
|
83
|
+
left_value <= right_value if comparable?(left_value, right_value)
|
92
84
|
end
|
93
85
|
end
|
94
86
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module JMESPath
|
2
3
|
# @api private
|
3
4
|
module Nodes
|
@@ -27,6 +28,7 @@ module JMESPath
|
|
27
28
|
|
28
29
|
class ComparatorCondition < Node
|
29
30
|
COMPARATOR_TO_CONDITION = {}
|
31
|
+
COMPARABLE_TYPES = [Numeric, String].freeze
|
30
32
|
|
31
33
|
def initialize(left, right, child)
|
32
34
|
@left = left
|
@@ -34,9 +36,17 @@ module JMESPath
|
|
34
36
|
@child = child
|
35
37
|
end
|
36
38
|
|
37
|
-
def visit(
|
39
|
+
def visit(_value)
|
38
40
|
nil
|
39
41
|
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def comparable?(left_value, right_value)
|
46
|
+
COMPARABLE_TYPES.any? do |type|
|
47
|
+
left_value.is_a?(type) && right_value.is_a?(type)
|
48
|
+
end
|
49
|
+
end
|
40
50
|
end
|
41
51
|
|
42
52
|
class EqCondition < ComparatorCondition
|
@@ -99,7 +109,7 @@ module JMESPath
|
|
99
109
|
def visit(value)
|
100
110
|
left_value = @left.visit(value)
|
101
111
|
right_value = @right.visit(value)
|
102
|
-
|
112
|
+
comparable?(left_value, right_value) && left_value > right_value ? @child.visit(value) : nil
|
103
113
|
end
|
104
114
|
end
|
105
115
|
|
@@ -109,7 +119,7 @@ module JMESPath
|
|
109
119
|
def visit(value)
|
110
120
|
left_value = @left.visit(value)
|
111
121
|
right_value = @right.visit(value)
|
112
|
-
|
122
|
+
comparable?(left_value, right_value) && left_value >= right_value ? @child.visit(value) : nil
|
113
123
|
end
|
114
124
|
end
|
115
125
|
|
@@ -119,7 +129,7 @@ module JMESPath
|
|
119
129
|
def visit(value)
|
120
130
|
left_value = @left.visit(value)
|
121
131
|
right_value = @right.visit(value)
|
122
|
-
|
132
|
+
comparable?(left_value, right_value) && left_value < right_value ? @child.visit(value) : nil
|
123
133
|
end
|
124
134
|
end
|
125
135
|
|
@@ -129,7 +139,7 @@ module JMESPath
|
|
129
139
|
def visit(value)
|
130
140
|
left_value = @left.visit(value)
|
131
141
|
right_value = @right.visit(value)
|
132
|
-
|
142
|
+
comparable?(left_value, right_value) && left_value <= right_value ? @child.visit(value) : nil
|
133
143
|
end
|
134
144
|
end
|
135
145
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module JMESPath
|
2
3
|
# @api private
|
3
4
|
module Nodes
|
@@ -8,7 +9,7 @@ module JMESPath
|
|
8
9
|
@expression = expression
|
9
10
|
end
|
10
11
|
|
11
|
-
def visit(
|
12
|
+
def visit(_value)
|
12
13
|
self
|
13
14
|
end
|
14
15
|
|
@@ -22,4 +23,3 @@ module JMESPath
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
25
|
-
|
data/lib/jmespath/nodes/field.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module JMESPath
|
2
3
|
# @api private
|
3
4
|
module Nodes
|
@@ -41,9 +42,7 @@ module JMESPath
|
|
41
42
|
def initialize(keys)
|
42
43
|
@keys = keys
|
43
44
|
@key_syms = keys.each_with_object({}) do |k, syms|
|
44
|
-
if k.respond_to?(:to_sym)
|
45
|
-
syms[k] = k.to_sym
|
46
|
-
end
|
45
|
+
syms[k] = k.to_sym if k.respond_to?(:to_sym)
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
@@ -70,10 +69,7 @@ module JMESPath
|
|
70
69
|
|
71
70
|
private
|
72
71
|
|
73
|
-
|
74
|
-
@keys
|
75
|
-
end
|
76
|
-
|
72
|
+
attr_reader :keys
|
77
73
|
end
|
78
74
|
end
|
79
75
|
end
|