janeway-jsonpath 0.6.0 → 1.1.0

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/janeway/ast/array_slice_selector.rb +6 -90
  4. data/lib/janeway/ast/binary_operator.rb +57 -51
  5. data/lib/janeway/ast/child_segment.rb +3 -5
  6. data/lib/janeway/ast/current_node.rb +2 -15
  7. data/lib/janeway/ast/descendant_segment.rb +0 -3
  8. data/lib/janeway/ast/expression.rb +35 -5
  9. data/lib/janeway/ast/function.rb +15 -10
  10. data/lib/janeway/ast/name_selector.rb +12 -7
  11. data/lib/janeway/ast/root_node.rb +2 -15
  12. data/lib/janeway/ast/selector.rb +5 -6
  13. data/lib/janeway/ast/unary_operator.rb +12 -2
  14. data/lib/janeway/ast/wildcard_selector.rb +2 -2
  15. data/lib/janeway/enumerator.rb +14 -7
  16. data/lib/janeway/error.rb +6 -1
  17. data/lib/janeway/functions/count.rb +1 -8
  18. data/lib/janeway/functions/length.rb +1 -12
  19. data/lib/janeway/functions/match.rb +3 -8
  20. data/lib/janeway/functions/search.rb +3 -8
  21. data/lib/janeway/functions/value.rb +1 -7
  22. data/lib/janeway/functions.rb +75 -2
  23. data/lib/janeway/interpreter.rb +50 -35
  24. data/lib/janeway/interpreters/array_slice_selector_delete_if.rb +10 -13
  25. data/lib/janeway/interpreters/array_slice_selector_interpreter.rb +56 -13
  26. data/lib/janeway/interpreters/binary_operator_interpreter.rb +18 -13
  27. data/lib/janeway/interpreters/descendant_segment_interpreter.rb +32 -13
  28. data/lib/janeway/interpreters/filter_selector_interpreter.rb +26 -34
  29. data/lib/janeway/interpreters/function_interpreter.rb +5 -1
  30. data/lib/janeway/interpreters/index_selector_delete_if.rb +1 -0
  31. data/lib/janeway/interpreters/index_selector_interpreter.rb +3 -1
  32. data/lib/janeway/interpreters/iteration_helper.rb +19 -5
  33. data/lib/janeway/interpreters/root_node_delete_if.rb +57 -16
  34. data/lib/janeway/interpreters/tree_constructor.rb +0 -20
  35. data/lib/janeway/interpreters/wildcard_selector_delete_if.rb +16 -0
  36. data/lib/janeway/interpreters/yielder.rb +8 -2
  37. data/lib/janeway/lexer.rb +66 -77
  38. data/lib/janeway/location.rb +3 -1
  39. data/lib/janeway/normalized_path.rb +23 -7
  40. data/lib/janeway/parser.rb +46 -34
  41. data/lib/janeway/query.rb +48 -5
  42. data/lib/janeway/token.rb +2 -5
  43. data/lib/janeway/version.rb +1 -1
  44. data/lib/janeway.rb +16 -3
  45. metadata +3 -10
  46. data/lib/janeway/interpreters/array_slice_selector_deleter.rb +0 -41
  47. data/lib/janeway/interpreters/child_segment_deleter.rb +0 -19
  48. data/lib/janeway/interpreters/filter_selector_deleter.rb +0 -65
  49. data/lib/janeway/interpreters/index_selector_deleter.rb +0 -26
  50. data/lib/janeway/interpreters/name_selector_deleter.rb +0 -27
  51. data/lib/janeway/interpreters/root_node_deleter.rb +0 -34
  52. data/lib/janeway/interpreters/wildcard_selector_deleter.rb +0 -32
@@ -16,6 +16,32 @@ module Janeway
16
16
  UNARY_OPERATORS = %w[! -].freeze
17
17
  BINARY_OPERATORS = %w[== != > < >= <= ,].freeze
18
18
  LOGICAL_OPERATORS = %w[&& ||].freeze
19
+
20
+ # O(1)-lookup Hash companions to the arrays above, plus the union used by
21
+ # determine_infix_function. Building these inline in the hot path
22
+ # allocated a fresh Array per token; hoisting eliminates it.
23
+ UNARY_OPERATOR_SET = UNARY_OPERATORS.each_with_object({}) { |op, h| h[op] = true }.freeze
24
+ BINARY_OPERATOR_SET = BINARY_OPERATORS.each_with_object({}) { |op, h| h[op] = true }.freeze
25
+ INFIX_OPERATOR_SET =
26
+ (BINARY_OPERATORS + LOGICAL_OPERATORS).each_with_object({}) { |op, h| h[op] = true }.freeze
27
+ PARSE_METHOD_TYPES =
28
+ %I[identifier number string true false nil function if while root current_node]
29
+ .each_with_object({}) { |t, h| h[t] = true }.freeze
30
+ TERMINATOR_TYPES = %I[child_end union eof].each_with_object({}) { |t, h| h[t] = true }.freeze
31
+
32
+ # O(1) dispatch table for determine_parsing_function's type-driven cases.
33
+ # Sits next to the PARSE_METHOD_TYPES set (the other type branch) so both
34
+ # are visible when adding a new token type.
35
+ PARSE_DISPATCH_BY_TYPE = {
36
+ group_start: :parse_grouped_expr,
37
+ :"\n" => :parse_terminator,
38
+ eof: :parse_terminator,
39
+ child_start: :parse_child_segment,
40
+ dot: :parse_dot_notation,
41
+ descendants: :parse_descendant_segment,
42
+ filter: :parse_filter_selector,
43
+ null: :parse_null,
44
+ }.freeze
19
45
  LOWEST_PRECEDENCE = 0
20
46
  OPERATOR_PRECEDENCE = {
21
47
  ',' => 0,
@@ -65,12 +91,8 @@ module Janeway
65
91
 
66
92
  private
67
93
 
68
- def pending_tokens?
69
- @next_p < tokens.length
70
- end
71
-
72
94
  def next_not_terminator?
73
- next_token && next_token.type != :"\n" && next_token.type != :eof
95
+ next_token && next_token.type != :eof
74
96
  end
75
97
 
76
98
  # Make "next" token become "current" by moving the pointer
@@ -135,33 +157,21 @@ module Janeway
135
157
  end
136
158
 
137
159
  def determine_parsing_function
138
- parse_methods = %I[identifier number string true false nil function if while root current_node]
139
- if parse_methods.include?(current.type)
140
- :"parse_#{current.type}"
141
- elsif current.type == :group_start # (
142
- :parse_grouped_expr
143
- elsif %I[\n eof].include?(current.type)
144
- :parse_terminator
145
- elsif UNARY_OPERATORS.include?(current.lexeme)
146
- :parse_unary_operator
147
- elsif current.type == :child_start # [
148
- :parse_child_segment
149
- elsif current.type == :dot # .
150
- :parse_dot_notation
151
- elsif current.type == :descendants # ..
152
- :parse_descendant_segment
153
- elsif current.type == :filter # ?
154
- :parse_filter_selector
155
- elsif current.type == :null # null
156
- :parse_null
157
- else
158
- raise err("Don't know how to parse #{current}")
159
- end
160
+ # Two type-driven tables plus a lexeme-driven check for unary operators.
161
+ # PARSE_METHOD_TYPES synthesizes the method name (`:parse_<type>`);
162
+ # PARSE_DISPATCH_BY_TYPE maps to a fixed method name.
163
+ return :"parse_#{current.type}" if PARSE_METHOD_TYPES.include?(current.type)
164
+
165
+ dispatch = PARSE_DISPATCH_BY_TYPE[current.type]
166
+ return dispatch if dispatch
167
+ return :parse_unary_operator if UNARY_OPERATOR_SET.include?(current.lexeme)
168
+
169
+ raise err("Don't know how to parse #{current}")
160
170
  end
161
171
 
162
172
  # @return [nil, Symbol]
163
173
  def determine_infix_function(token = current)
164
- return unless (BINARY_OPERATORS + LOGICAL_OPERATORS).include?(token.lexeme)
174
+ return unless INFIX_OPERATOR_SET.include?(token.lexeme)
165
175
 
166
176
  :parse_binary_operator
167
177
  end
@@ -198,14 +208,16 @@ module Janeway
198
208
  end
199
209
 
200
210
  # '-' must be followed by a number token.
201
- # Parse number and apply - sign to its literal value
211
+ # Consume the minus, then replace the following number token in the
212
+ # token stream with a copy that has the negated literal. Replacing —
213
+ # rather than mutating in place — keeps Token immutable.
202
214
  consume
203
- parse_number
204
215
  unless current.literal.is_a?(Numeric)
205
216
  raise err("Minus operator \"-\" must be followed by number, got #{current.lexeme.inspect}")
206
217
  end
207
218
 
208
- current.literal *= -1
219
+ original = current
220
+ @tokens[@next_p - 1] = Token.new(original.type, original.lexeme, -original.literal, original.location)
209
221
  current
210
222
  end
211
223
 
@@ -481,11 +493,10 @@ module Janeway
481
493
  # Feed tokens to the FilterSelector until hitting a terminator
482
494
  def parse_filter_selector
483
495
  selector = AST::FilterSelector.new
484
- terminator_types = %I[child_end union eof]
485
- while next_token && !terminator_types.include?(next_token.type)
496
+ while next_token && !TERMINATOR_TYPES.include?(next_token.type)
486
497
  consume
487
498
  node =
488
- if BINARY_OPERATORS.include?(current.lexeme)
499
+ if BINARY_OPERATOR_SET.include?(current.lexeme)
489
500
  parse_binary_operator(selector.value)
490
501
  else
491
502
  parse_expr_recursively
@@ -529,6 +540,7 @@ module Janeway
529
540
 
530
541
  consume
531
542
  op.right = parse_expr_recursively(op_precedence)
543
+ op.validate!
532
544
 
533
545
  op
534
546
  end
data/lib/janeway/query.rb CHANGED
@@ -43,6 +43,26 @@ module Janeway
43
43
  @root.singular_query?
44
44
  end
45
45
 
46
+ # Return a cached interpreter tree for the given type, building it via
47
+ # the block on the first call. Only stateless interpreter types
48
+ # (`:finder`, `:deleter`) benefit from caching — `:iterator` and
49
+ # `:delete_if` capture the caller's block, so their trees are
50
+ # per-call.
51
+ #
52
+ # No-op (yields fresh every time) if the Query is frozen — respecting
53
+ # the docstring's "can be frozen" contract.
54
+ #
55
+ # @param type [Symbol] :finder, :deleter, :iterator, :delete_if
56
+ # @yield build the tree if not cached
57
+ # @return [Interpreters::Base]
58
+ def interpreter_tree_for(type)
59
+ return yield unless %i[finder deleter].include?(type)
60
+ return yield if frozen?
61
+
62
+ @interpreter_tree_cache ||= {}
63
+ @interpreter_tree_cache[type] ||= yield
64
+ end
65
+
46
66
  # Return a list of the nodes in the AST.
47
67
  # The AST of a jsonpath query is a straight line, so this is expressible as an array.
48
68
  # The only part of the AST with branches is inside a filter selector, but that doesn't show up here.
@@ -76,10 +96,23 @@ module Janeway
76
96
  result.flatten.join("\n")
77
97
  end
78
98
 
79
- # Deep copy the query
99
+ # Deep copy the query.
100
+ #
101
+ # Only the top-level linked list of segments/selectors is cloned — that is
102
+ # the only part `pop` mutates. Nested contents (filter expressions,
103
+ # function parameters, child-segment members) are shared with the original,
104
+ # which is safe because the interpreter never mutates the AST.
105
+ #
106
+ # The tree cache is intentionally NOT shared with the dup: cached trees
107
+ # reference the original's top-level chain and are invalid for a dup that
108
+ # may later be popped.
109
+ #
80
110
  # @return [Query]
81
111
  def dup
82
- Parser.parse(to_s)
112
+ cloned = node_list.map(&:dup)
113
+ cloned.each_cons(2) { |a, b| a.next = b }
114
+ cloned.last.next = nil
115
+ Query.new(cloned.first, @jsonpath)
83
116
  end
84
117
 
85
118
  # Delete the last element from the chain of selectors.
@@ -90,9 +123,7 @@ module Janeway
90
123
  #
91
124
  # @return [AST::Selector]
92
125
  def pop
93
- unless singular_query?
94
- raise Janeway::Error.new('not allowed to pop from a non-singular query', to_s)
95
- end
126
+ raise Janeway::Error.new('not allowed to pop from a non-singular query', to_s) unless singular_query?
96
127
 
97
128
  # Sever the link to the last selector
98
129
  nodes = node_list
@@ -106,5 +137,17 @@ module Janeway
106
137
  # Return the last selector
107
138
  nodes.last
108
139
  end
140
+
141
+ # Return a data-free split of this singular query into a "parent" Query
142
+ # plus the leaf selector — the parent addresses one level up from what
143
+ # `self` addresses. Used by Enumerator#insert to locate the container
144
+ # that a new value should be inserted into.
145
+ #
146
+ # @return [Array(Query, AST::Selector)] [parent_query, leaf_selector]
147
+ def parent_query
148
+ parent = dup
149
+ leaf = parent.pop
150
+ [parent, leaf]
151
+ end
109
152
  end
110
153
  end
data/lib/janeway/token.rb CHANGED
@@ -7,10 +7,7 @@ module Janeway
7
7
  class Token
8
8
  extend Forwardable
9
9
 
10
- attr_reader :type, :lexeme, :location
11
-
12
- # write-access so '-' operator can modify number value
13
- attr_accessor :literal
10
+ attr_reader :type, :lexeme, :literal, :location
14
11
 
15
12
  def_delegators :@location, :line, :col, :length
16
13
 
@@ -31,7 +28,7 @@ module Janeway
31
28
  when Integer, String then @literal == other
32
29
  when Symbol then @type == other
33
30
  when Token
34
- @type == other.type && @lexeme == other.lexem && @literal = other.literal
31
+ @type == other.type && @lexeme == other.lexeme && @literal == other.literal
35
32
  else
36
33
  raise ArgumentError, "don't know how to compare Token with #{other.inspect}"
37
34
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Janeway
4
4
  # Version for janeway-jsonpath gem
5
- VERSION = '0.6.0'
5
+ VERSION = '1.1.0'
6
6
  end
data/lib/janeway.rb CHANGED
@@ -54,8 +54,8 @@ module Janeway
54
54
  Janeway::Parser.parse(query)
55
55
  end
56
56
 
57
- # Transform a jsonpath singular query into an array of values suitable for
58
- # providing to Hash#dig or Array#dig.
57
+ # Transform a jsonpath singular query into an array of hash keys and/or array
58
+ # indexes suitable for providing to Hash#dig or Array#dig.
59
59
  #
60
60
  # Only singular queries are allowed, meaning queries that contain only name
61
61
  # selectors (ie. hash keys) and index selectors (array indexes.)
@@ -67,6 +67,19 @@ module Janeway
67
67
  # @param jsonpath [String] jsonpath query
68
68
  # @return [Array<String, Integer>]
69
69
  def self.path_to_diggable(jsonpath)
70
- raise NotImplementedError
70
+ raise Janeway::Error.new('Query has nothing to dig', jsonpath) if jsonpath == '$'
71
+
72
+ # Parse query and determine whether it can be converted
73
+ query = parse(jsonpath)
74
+ unless query.singular_query?
75
+ raise Janeway::Error.new('Only a singular query can be converted to dig parameters', jsonpath)
76
+ end
77
+
78
+ # Convert query to a list of name and index selectors
79
+ nodes = query.node_list
80
+ nodes.shift # discard the root identifier
81
+
82
+ # Extract values from selectors
83
+ nodes.map(&:value)
71
84
  end
72
85
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: janeway-jsonpath
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fraser Hanson
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-02-05 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: |+
13
13
  JSONPath is a query language for selecting and extracting values from a JSON text.
@@ -62,33 +62,26 @@ files:
62
62
  - lib/janeway/functions/value.rb
63
63
  - lib/janeway/interpreter.rb
64
64
  - lib/janeway/interpreters/array_slice_selector_delete_if.rb
65
- - lib/janeway/interpreters/array_slice_selector_deleter.rb
66
65
  - lib/janeway/interpreters/array_slice_selector_interpreter.rb
67
66
  - lib/janeway/interpreters/base.rb
68
67
  - lib/janeway/interpreters/binary_operator_interpreter.rb
69
68
  - lib/janeway/interpreters/child_segment_delete_if.rb
70
- - lib/janeway/interpreters/child_segment_deleter.rb
71
69
  - lib/janeway/interpreters/child_segment_interpreter.rb
72
70
  - lib/janeway/interpreters/current_node_interpreter.rb
73
71
  - lib/janeway/interpreters/descendant_segment_interpreter.rb
74
72
  - lib/janeway/interpreters/filter_selector_delete_if.rb
75
- - lib/janeway/interpreters/filter_selector_deleter.rb
76
73
  - lib/janeway/interpreters/filter_selector_interpreter.rb
77
74
  - lib/janeway/interpreters/function_interpreter.rb
78
75
  - lib/janeway/interpreters/index_selector_delete_if.rb
79
- - lib/janeway/interpreters/index_selector_deleter.rb
80
76
  - lib/janeway/interpreters/index_selector_interpreter.rb
81
77
  - lib/janeway/interpreters/iteration_helper.rb
82
78
  - lib/janeway/interpreters/name_selector_delete_if.rb
83
- - lib/janeway/interpreters/name_selector_deleter.rb
84
79
  - lib/janeway/interpreters/name_selector_interpreter.rb
85
80
  - lib/janeway/interpreters/root_node_delete_if.rb
86
- - lib/janeway/interpreters/root_node_deleter.rb
87
81
  - lib/janeway/interpreters/root_node_interpreter.rb
88
82
  - lib/janeway/interpreters/tree_constructor.rb
89
83
  - lib/janeway/interpreters/unary_operator_interpreter.rb
90
84
  - lib/janeway/interpreters/wildcard_selector_delete_if.rb
91
- - lib/janeway/interpreters/wildcard_selector_deleter.rb
92
85
  - lib/janeway/interpreters/wildcard_selector_interpreter.rb
93
86
  - lib/janeway/interpreters/yielder.rb
94
87
  - lib/janeway/lexer.rb
@@ -116,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
109
  - !ruby/object:Gem::Version
117
110
  version: '0'
118
111
  requirements: []
119
- rubygems_version: 3.6.2
112
+ rubygems_version: 4.0.8
120
113
  specification_version: 4
121
114
  summary: jsonpath parser which implements the finalized IETF standard of Goessner
122
115
  JSONPath
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'array_slice_selector_interpreter'
4
-
5
- module Janeway
6
- module Interpreters
7
- # Interprets array slice selector and deletes matching values
8
- class ArraySliceSelectorDeleter < ArraySliceSelectorInterpreter
9
- # Delete values matched by the array slice selector
10
- #
11
- # @param input [Array, Hash] the results of processing so far
12
- # @param _parent [Array, Hash] parent of the input object
13
- # @param _root [Array, Hash] the entire input
14
- # @param _path [Array<String>] elements of normalized path to the current input
15
- # @return [Array]
16
- def interpret(input, _parent, _root, _path)
17
- return [] unless input.is_a?(Array)
18
- return [] if selector&.step&.zero? # RFC: When step is 0, no elements are selected.
19
-
20
- # Calculate the upper and lower indices of the target range
21
- lower = selector.lower_index(input.size)
22
- upper = selector.upper_index(input.size)
23
-
24
- # Convert bounds and step to index values.
25
- # Omit the final index, since no value is collected for that.
26
- # Delete indexes from largest to smallest, so that deleting an index does
27
- # not change the remaining indexes
28
- results = []
29
- if selector.step.positive?
30
- indexes = lower.step(to: upper - 1, by: selector.step).to_a
31
- indexes.reverse_each { |i| results << input.delete_at(i) }
32
- results.reverse
33
- else
34
- indexes = upper.step(to: lower + 1, by: selector.step).to_a
35
- indexes.each { |i| results << input.delete_at(i) }
36
- results
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'child_segment_interpreter'
4
-
5
- module Janeway
6
- module Interpreters
7
- # Child segment interpreter with selectors that delete matching elements
8
- class ChildSegmentDeleter < ChildSegmentInterpreter
9
- # @param child_segment [AST::ChildSegment]
10
- def initialize(child_segment)
11
- super
12
- @selectors =
13
- child_segment.map do |expr|
14
- TreeConstructor.ast_node_to_deleter(expr)
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'filter_selector_interpreter'
4
-
5
- module Janeway
6
- module Interpreters
7
- # Interprets a filter selector, and deletes matching values
8
- class FilterSelectorDeleter < FilterSelectorInterpreter
9
- # Interpret selector on the input.
10
- # @param input [Hash] the results of processing so far
11
- # @param root [Array, Hash] the entire input
12
- # @param _path [Array<String>] elements of normalized path to the current input
13
- def interpret_hash(input, root, _path)
14
- # Apply filter expressions to the input data
15
- results = []
16
- input.each do |key, value|
17
- # Run filter and interpret result
18
- result = @expr.interpret(value, nil, root, [])
19
- case result
20
- when TrueClass then results << value # comparison test - pass
21
- when FalseClass then next # comparison test - fail
22
- when Array
23
- next if result.empty?
24
-
25
- results << value # existence test - node list
26
- else
27
- results << value # existence test. Null values here == success.
28
- end
29
- input.delete(key)
30
- end
31
- results
32
- end
33
-
34
- # Interpret selector on the input.
35
- # @param input [Array] the results of processing so far
36
- # @param root [Array, Hash] the entire input
37
- # @param _path [Array<String>] elements of normalized path to the current input
38
- def interpret_array(input, root, _path)
39
- # Apply filter expressions to the input data
40
- results = []
41
-
42
- # Iterate in reverse order so that deletion does not alter the remaining indexes
43
- i = input.size
44
- input.reverse_each do |value|
45
- i -= 1 # calculate array index
46
-
47
- # Run filter and interpret result
48
- result = @expr.interpret(value, nil, root, [])
49
- case result
50
- when TrueClass then results << value # comparison test - pass
51
- when FalseClass then next # comparison test - fail
52
- when Array
53
- next if result.empty?
54
-
55
- results << value # existence test - node list
56
- else
57
- results << value # existence test. Null values here == success.
58
- end
59
- input.delete_at(i)
60
- end
61
- results.reverse
62
- end
63
- end
64
- end
65
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'index_selector_interpreter'
4
-
5
- module Janeway
6
- module Interpreters
7
- # Interprets an index selector, and deletes the matched value.
8
- class IndexSelectorDeleter < IndexSelectorInterpreter
9
- # Interpret selector on the given input.
10
- # @param input [Array, Hash] the results of processing so far
11
- # @param _parent [Array, Hash] parent of the input object
12
- # @param _root [Array, Hash] the entire input
13
- # @param _path [Array<String>] elements of normalized path to the current input
14
- def interpret(input, _parent, _root, _path)
15
- return [] unless input.is_a?(Array)
16
-
17
- index = selector.value
18
- result = input.fetch(index) # raises IndexError if no such index
19
- input.delete_at(index) # returns nil if deleted value is nil, or if no value was deleted
20
- [result]
21
- rescue IndexError
22
- []
23
- end
24
- end
25
- end
26
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'name_selector_interpreter'
4
-
5
- module Janeway
6
- module Interpreters
7
- # Interprets a name selector, and deletes the matched values.
8
- class NameSelectorDeleter < NameSelectorInterpreter
9
- # Interpret selector on the given input.
10
- # @param input [Array, Hash] the results of processing so far
11
- # @param _parent [Array, Hash] parent of the input object
12
- # @param _root [Array, Hash] the entire input
13
- # @param _path [Array<String>] elements of normalized path to the current input
14
- def interpret(input, _parent, _root, _path)
15
- return [] unless input.is_a?(Hash) && input.key?(name)
16
-
17
- [input.delete(name)]
18
- end
19
-
20
- # Return hash representation of this interpreter
21
- # @return [Hash]
22
- def as_json
23
- { type: type, value: name, next: @next&.as_json }
24
- end
25
- end
26
- end
27
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'root_node_interpreter'
4
-
5
- module Janeway
6
- module Interpreters
7
- # Interprets the root node for deletion
8
- class RootNodeDeleter < RootNodeInterpreter
9
- # Delete all values from the root node.
10
- #
11
- # TODO: unclear, for deletion is there a difference between queries '$' and '$.*'?
12
- #
13
- # @param _input [Array, Hash] the results of processing so far
14
- # @param _parent [Array, Hash] parent of the input object
15
- # @param root [Array, Hash] the entire input
16
- # @param _path [Array<String>] elements of normalized path to the current input
17
- # @return [Array] deleted elements
18
- def interpret(_input, _parent, root, _path)
19
- case root
20
- when Array
21
- results = root.dup
22
- root.clear
23
- results
24
- when Hash
25
- results = root.values
26
- root.clear
27
- results
28
- else
29
- []
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'wildcard_selector_interpreter'
4
-
5
- module Janeway
6
- module Interpreters
7
- # Interprets a wildcard selector, and deletes the results.
8
- class WildcardSelectorDeleter < WildcardSelectorInterpreter
9
- # Delete all elements from the input
10
- #
11
- # @param input [Array, Hash] the results of processing so far
12
- # @param _parent [Array, Hash] parent of the input object
13
- # @param _root [Array, Hash] the entire input
14
- # @param _path [Array<String>] elements of normalized path to the current input
15
- # @return [Array] deleted elements
16
- def interpret(input, _parent, _root, _path)
17
- case input
18
- when Array
19
- results = input.dup
20
- input.clear
21
- results
22
- when Hash
23
- results = input.values
24
- input.clear
25
- results
26
- else
27
- []
28
- end
29
- end
30
- end
31
- end
32
- end