json_p3 0.4.0 → 1.0.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.rubocop.yml +26 -7
- data/.ruby-version +1 -1
- data/CHANGELOG.md +58 -0
- data/README.md +125 -123
- data/Rakefile +3 -3
- data/certs/jgrp.pem +21 -21
- data/lib/json_p3/errors.rb +51 -43
- data/lib/json_p3/patch/op.rb +23 -0
- data/lib/json_p3/patch/op_add.rb +51 -0
- data/lib/json_p3/patch/op_copy.rb +64 -0
- data/lib/json_p3/patch/op_move.rb +74 -0
- data/lib/json_p3/patch/op_remove.rb +56 -0
- data/lib/json_p3/patch/op_replace.rb +54 -0
- data/lib/json_p3/patch/op_test.rb +31 -0
- data/lib/json_p3/patch.rb +15 -330
- data/lib/json_p3/path/environment.rb +113 -0
- data/lib/json_p3/path/filter.rb +463 -0
- data/lib/json_p3/path/function.rb +12 -0
- data/lib/json_p3/path/function_extensions/count.rb +15 -0
- data/lib/json_p3/path/function_extensions/length.rb +17 -0
- data/lib/json_p3/path/function_extensions/match.rb +62 -0
- data/lib/json_p3/path/function_extensions/pattern.rb +42 -0
- data/lib/json_p3/path/function_extensions/search.rb +44 -0
- data/lib/json_p3/path/function_extensions/value.rb +15 -0
- data/lib/json_p3/path/lexer.rb +220 -0
- data/lib/json_p3/path/node.rb +48 -0
- data/lib/json_p3/path/parser.rb +676 -0
- data/lib/json_p3/path/query.rb +74 -0
- data/lib/json_p3/path/segment.rb +172 -0
- data/lib/json_p3/path/selector.rb +304 -0
- data/lib/json_p3/path/serialize.rb +16 -0
- data/lib/json_p3/path/unescape.rb +134 -0
- data/lib/json_p3/pointer.rb +15 -76
- data/lib/json_p3/relative_pointer.rb +69 -0
- data/lib/json_p3/version.rb +1 -1
- data/lib/json_p3.rb +50 -13
- data/sig/json_p3/cache.rbs +21 -0
- data/sig/json_p3/errors.rbs +55 -0
- data/sig/json_p3/patch.rbs +145 -0
- data/sig/json_p3/path/environment.rbs +81 -0
- data/sig/json_p3/path/filter.rbs +196 -0
- data/sig/json_p3/path/function.rbs +94 -0
- data/sig/json_p3/path/lexer.rbs +62 -0
- data/sig/json_p3/path/node.rbs +46 -0
- data/sig/json_p3/path/parser.rbs +92 -0
- data/sig/json_p3/path/query.rbs +47 -0
- data/sig/json_p3/path/segment.rbs +54 -0
- data/sig/json_p3/path/selector.rbs +100 -0
- data/sig/json_p3/path/serialize.rbs +9 -0
- data/sig/json_p3/path/unescape.rbs +12 -0
- data/sig/json_p3/pointer.rbs +64 -0
- data/sig/json_p3/relative_pointer.rbs +30 -0
- data/sig/json_p3.rbs +24 -1313
- data.tar.gz.sig +0 -0
- metadata +66 -46
- metadata.gz.sig +0 -0
- data/lib/json_p3/environment.rb +0 -111
- data/lib/json_p3/filter.rb +0 -459
- data/lib/json_p3/function.rb +0 -10
- data/lib/json_p3/function_extensions/count.rb +0 -15
- data/lib/json_p3/function_extensions/length.rb +0 -17
- data/lib/json_p3/function_extensions/match.rb +0 -62
- data/lib/json_p3/function_extensions/pattern.rb +0 -39
- data/lib/json_p3/function_extensions/search.rb +0 -44
- data/lib/json_p3/function_extensions/value.rb +0 -15
- data/lib/json_p3/lexer.rb +0 -419
- data/lib/json_p3/node.rb +0 -44
- data/lib/json_p3/parser.rb +0 -553
- data/lib/json_p3/path.rb +0 -72
- data/lib/json_p3/segment.rb +0 -158
- data/lib/json_p3/selector.rb +0 -306
- data/lib/json_p3/serialize.rb +0 -13
- data/lib/json_p3/token.rb +0 -36
- data/lib/json_p3/unescape.rb +0 -112
data/lib/json_p3/pointer.rb
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "errors"
|
|
4
|
-
|
|
5
3
|
module JSONP3
|
|
6
4
|
# Identify a single value in JSON-like data, as per RFC 6901.
|
|
7
|
-
class
|
|
5
|
+
class Pointer
|
|
8
6
|
RE_INT = /\A(0|[1-9][0-9]*)\z/
|
|
9
7
|
UNDEFINED = :__undefined
|
|
10
8
|
|
|
11
9
|
attr_reader :tokens
|
|
12
10
|
|
|
11
|
+
def self.resolve(pointer, value, default: UNDEFINED)
|
|
12
|
+
new(pointer).resolve(value, default: default)
|
|
13
|
+
end
|
|
14
|
+
|
|
13
15
|
# Encode an array of strings and integers into a JSON Pointer.
|
|
14
16
|
# @param tokens [Array<String | Integer> | nil]
|
|
15
17
|
# @return [String]
|
|
@@ -26,7 +28,7 @@ module JSONP3
|
|
|
26
28
|
# @param pointer [String]
|
|
27
29
|
def initialize(pointer)
|
|
28
30
|
@tokens = parse(pointer)
|
|
29
|
-
@pointer =
|
|
31
|
+
@pointer = Pointer.encode(@tokens)
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
# Resolve this pointer against JSON-like data _value_.
|
|
@@ -63,14 +65,14 @@ module JSONP3
|
|
|
63
65
|
end
|
|
64
66
|
|
|
65
67
|
# Return true if this pointer is relative to _pointer_.
|
|
66
|
-
# @param pointer [
|
|
68
|
+
# @param pointer [Pointer]
|
|
67
69
|
# @return [bool]
|
|
68
70
|
def relative_to?(pointer)
|
|
69
71
|
pointer.tokens.length < @tokens.length && @tokens[...pointer.tokens.length] == pointer.tokens
|
|
70
72
|
end
|
|
71
73
|
|
|
72
74
|
# @param parts [String]
|
|
73
|
-
# @return [
|
|
75
|
+
# @return [Pointer]
|
|
74
76
|
def join(*parts)
|
|
75
77
|
pointer = self
|
|
76
78
|
parts.each do |part|
|
|
@@ -91,14 +93,14 @@ module JSONP3
|
|
|
91
93
|
def parent
|
|
92
94
|
return self if @tokens.empty?
|
|
93
95
|
|
|
94
|
-
|
|
96
|
+
Pointer.new(Pointer.encode(@tokens[...-1] || raise))
|
|
95
97
|
end
|
|
96
98
|
|
|
97
99
|
# Return a new pointer relative to this pointer using Relative JSON Pointer syntax.
|
|
98
|
-
# @param rel [String |
|
|
99
|
-
# @return [
|
|
100
|
+
# @param rel [String | RelativePointer]
|
|
101
|
+
# @return [Pointer]
|
|
100
102
|
def to(rel)
|
|
101
|
-
p = rel.is_a?(String) ?
|
|
103
|
+
p = rel.is_a?(String) ? RelativePointer.new(rel) : rel
|
|
102
104
|
p.to(self)
|
|
103
105
|
end
|
|
104
106
|
|
|
@@ -112,7 +114,7 @@ module JSONP3
|
|
|
112
114
|
# @return [Array<String | Integer>]
|
|
113
115
|
def parse(pointer)
|
|
114
116
|
if pointer.length.positive? && !pointer.start_with?("/")
|
|
115
|
-
raise
|
|
117
|
+
raise JSONP3::Pointer::SyntaxError,
|
|
116
118
|
"pointers must start with a slash or be the empty string"
|
|
117
119
|
end
|
|
118
120
|
|
|
@@ -164,73 +166,10 @@ module JSONP3
|
|
|
164
166
|
end
|
|
165
167
|
|
|
166
168
|
def _join(other)
|
|
167
|
-
raise
|
|
169
|
+
raise JSONP3::Pointer::TypeError, "unsupported join part" unless other.is_a?(String)
|
|
168
170
|
|
|
169
171
|
part = other.lstrip
|
|
170
|
-
part.start_with?("/") ?
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
# A relative JSON Pointer.
|
|
175
|
-
# See https://datatracker.ietf.org/doc/html/draft-hha-relative-json-pointer
|
|
176
|
-
class RelativeJSONPointer
|
|
177
|
-
RE_RELATIVE_POINTER = /\A(?<ORIGIN>\d+)(?<INDEX_G>(?<SIGN>[+-])(?<INDEX>\d))?(?<POINTER>.*)\z/m
|
|
178
|
-
RE_INT = /\A(0|[1-9][0-9]*)\z/
|
|
179
|
-
|
|
180
|
-
# @param rel [String]
|
|
181
|
-
def initialize(rel)
|
|
182
|
-
match = RE_RELATIVE_POINTER.match(rel)
|
|
183
|
-
|
|
184
|
-
raise JSONPointerSyntaxError, "failed to parse relative pointer" if match.nil?
|
|
185
|
-
|
|
186
|
-
@origin = parse_int(match[:ORIGIN] || raise)
|
|
187
|
-
@index = 0
|
|
188
|
-
|
|
189
|
-
if match[:INDEX_G]
|
|
190
|
-
@index = parse_int(match[:INDEX] || raise)
|
|
191
|
-
raise JSONPointerSyntaxError, "index offset can't be zero" if @index.zero?
|
|
192
|
-
|
|
193
|
-
@index = -@index if match[:SIGN] == "-"
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
@pointer = match[:POINTER] == "#" ? "#" : JSONPointer.new(match[:POINTER] || raise)
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
def to_s
|
|
200
|
-
sign = @index.positive? ? "+" : ""
|
|
201
|
-
index = @index.zero? ? "" : "#{sign}#{@index}"
|
|
202
|
-
"#{@origin}#{index}#{@pointer}"
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
# Return a new JSON Pointer by applying this relative pointer to _pointer_.
|
|
206
|
-
# @param pointer [String | JSONPointer]
|
|
207
|
-
# @return [JSONPointer]
|
|
208
|
-
def to(pointer)
|
|
209
|
-
p = pointer.is_a?(String) ? JSONPointer.new(pointer) : pointer
|
|
210
|
-
|
|
211
|
-
raise JSONPointerIndexError, "origin (#{@origin}) exceeds root (#{p.tokens.length})" if @origin > p.tokens.length
|
|
212
|
-
|
|
213
|
-
tokens = @origin < 1 ? p.tokens[0..] || raise : p.tokens[0...-@origin] || raise
|
|
214
|
-
tokens[-1] = (tokens[-1] || raise) + @index if @index != 0 && tokens.length.positive? && tokens[-1].is_a?(Integer)
|
|
215
|
-
|
|
216
|
-
if @pointer == "#"
|
|
217
|
-
tokens[-1] = "##{tokens[-1]}"
|
|
218
|
-
else
|
|
219
|
-
tokens.concat(@pointer.tokens) # steep:ignore
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
JSONPointer.new(JSONPointer.encode(tokens))
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
private
|
|
226
|
-
|
|
227
|
-
# @param token [String]
|
|
228
|
-
# @return [Integer]
|
|
229
|
-
def parse_int(token)
|
|
230
|
-
raise JSONPointerSyntaxError, "unexpected leading zero" if token.start_with?("0") && token.length > 1
|
|
231
|
-
raise JSONPointerSyntaxError, "expected an integer, found '#{token}'" unless RE_INT.match?(token)
|
|
232
|
-
|
|
233
|
-
token.to_i
|
|
172
|
+
part.start_with?("/") ? Pointer.new(part) : Pointer.new(Pointer.encode(@tokens + _parse(part)))
|
|
234
173
|
end
|
|
235
174
|
end
|
|
236
175
|
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JSONP3
|
|
4
|
+
# A relative JSON Pointer.
|
|
5
|
+
# See https://datatracker.ietf.org/doc/html/draft-hha-relative-json-pointer
|
|
6
|
+
class RelativePointer
|
|
7
|
+
RE_RELATIVE_POINTER = /\A(?<ORIGIN>\d+)(?<INDEX_G>(?<SIGN>[+-])(?<INDEX>\d))?(?<POINTER>.*)\z/m
|
|
8
|
+
RE_INT = /\A(0|[1-9][0-9]*)\z/
|
|
9
|
+
|
|
10
|
+
# @param rel [String]
|
|
11
|
+
def initialize(rel)
|
|
12
|
+
match = RE_RELATIVE_POINTER.match(rel)
|
|
13
|
+
|
|
14
|
+
raise JSONP3::Pointer::SyntaxError, "failed to parse relative pointer" if match.nil?
|
|
15
|
+
|
|
16
|
+
@origin = parse_int(match[:ORIGIN] || raise)
|
|
17
|
+
@index = 0
|
|
18
|
+
|
|
19
|
+
if match[:INDEX_G]
|
|
20
|
+
@index = parse_int(match[:INDEX] || raise)
|
|
21
|
+
raise JSONP3::Pointer::SyntaxError, "index offset can't be zero" if @index.zero?
|
|
22
|
+
|
|
23
|
+
@index = -@index if match[:SIGN] == "-"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
@pointer = match[:POINTER] == "#" ? "#" : Pointer.new(match[:POINTER] || raise)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_s
|
|
30
|
+
sign = @index.positive? ? "+" : ""
|
|
31
|
+
index = @index.zero? ? "" : "#{sign}#{@index}"
|
|
32
|
+
"#{@origin}#{index}#{@pointer}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Return a new JSON Pointer by applying this relative pointer to _pointer_.
|
|
36
|
+
# @param pointer [String | Pointer]
|
|
37
|
+
# @return [Pointer]
|
|
38
|
+
def to(pointer)
|
|
39
|
+
p = pointer.is_a?(String) ? Pointer.new(pointer) : pointer
|
|
40
|
+
|
|
41
|
+
if @origin > p.tokens.length
|
|
42
|
+
raise JSONP3::Pointer::IndexError,
|
|
43
|
+
"origin (#{@origin}) exceeds root (#{p.tokens.length})"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
tokens = @origin < 1 ? p.tokens[0..] || raise : p.tokens[0...-@origin] || raise
|
|
47
|
+
tokens[-1] = (tokens[-1] || raise) + @index if @index != 0 && tokens.length.positive? && tokens[-1].is_a?(Integer)
|
|
48
|
+
|
|
49
|
+
if @pointer == "#"
|
|
50
|
+
tokens[-1] = "##{tokens[-1]}"
|
|
51
|
+
else
|
|
52
|
+
tokens.concat(@pointer.tokens) # steep:ignore
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
Pointer.new(Pointer.encode(tokens))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
# @param token [String]
|
|
61
|
+
# @return [Integer]
|
|
62
|
+
def parse_int(token)
|
|
63
|
+
raise JSONP3::Pointer::SyntaxError, "unexpected leading zero" if token.start_with?("0") && token.length > 1
|
|
64
|
+
raise JSONP3::Pointer::SyntaxError, "expected an integer, found '#{token}'" unless RE_INT.match?(token)
|
|
65
|
+
|
|
66
|
+
token.to_i
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
data/lib/json_p3/version.rb
CHANGED
data/lib/json_p3.rb
CHANGED
|
@@ -1,43 +1,80 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "json_p3/version"
|
|
4
|
-
require_relative "json_p3/
|
|
4
|
+
require_relative "json_p3/errors"
|
|
5
|
+
require_relative "json_p3/cache"
|
|
6
|
+
require_relative "json_p3/path/environment"
|
|
5
7
|
require_relative "json_p3/pointer"
|
|
8
|
+
require_relative "json_p3/relative_pointer"
|
|
6
9
|
require_relative "json_p3/patch"
|
|
10
|
+
require_relative "json_p3/patch/op"
|
|
11
|
+
require_relative "json_p3/patch/op_add"
|
|
12
|
+
require_relative "json_p3/patch/op_copy"
|
|
13
|
+
require_relative "json_p3/patch/op_move"
|
|
14
|
+
require_relative "json_p3/patch/op_remove"
|
|
15
|
+
require_relative "json_p3/patch/op_replace"
|
|
16
|
+
require_relative "json_p3/patch/op_test"
|
|
7
17
|
|
|
8
|
-
#
|
|
18
|
+
# JSONPath, JSON Pointer and JSONPatch.
|
|
9
19
|
module JSONP3
|
|
10
|
-
|
|
20
|
+
# JSONPath query expressions.
|
|
21
|
+
module Path
|
|
22
|
+
DefaultEnvironment = JSONP3::Path::Environment.new
|
|
23
|
+
|
|
24
|
+
def self.find(path, data)
|
|
25
|
+
DefaultEnvironment.find(path, data)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.find_enum(path, data)
|
|
29
|
+
DefaultEnvironment.find_enum(path, data)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.compile(path)
|
|
33
|
+
DefaultEnvironment.compile(path)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.match(path, data)
|
|
37
|
+
DefaultEnvironment.match(path, data)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.match?(path, data)
|
|
41
|
+
DefaultEnvironment.match?(path, data)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.first(path, data)
|
|
45
|
+
DefaultEnvironment.first(path, data)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
11
48
|
|
|
12
49
|
def self.find(path, data)
|
|
13
|
-
|
|
50
|
+
Path.find(path, data)
|
|
14
51
|
end
|
|
15
52
|
|
|
16
53
|
def self.find_enum(path, data)
|
|
17
|
-
|
|
54
|
+
Path.find_enum(path, data)
|
|
18
55
|
end
|
|
19
56
|
|
|
20
57
|
def self.compile(path)
|
|
21
|
-
|
|
58
|
+
Path.compile(path)
|
|
22
59
|
end
|
|
23
60
|
|
|
24
61
|
def self.match(path, data)
|
|
25
|
-
|
|
62
|
+
Path.match(path, data)
|
|
26
63
|
end
|
|
27
64
|
|
|
28
65
|
def self.match?(path, data)
|
|
29
|
-
|
|
66
|
+
Path.match?(path, data)
|
|
30
67
|
end
|
|
31
68
|
|
|
32
69
|
def self.first(path, data)
|
|
33
|
-
|
|
70
|
+
Path.first(path, data)
|
|
34
71
|
end
|
|
35
72
|
|
|
36
|
-
def self.resolve(pointer, value, default:
|
|
37
|
-
|
|
73
|
+
def self.resolve(pointer, value, default: Pointer::UNDEFINED)
|
|
74
|
+
Pointer.resolve(pointer, value, default: default)
|
|
38
75
|
end
|
|
39
76
|
|
|
40
|
-
def self.apply(ops, value)
|
|
41
|
-
|
|
77
|
+
def self.apply!(ops, value)
|
|
78
|
+
Patch.apply!(ops, value)
|
|
42
79
|
end
|
|
43
80
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module JSONP3
|
|
2
|
+
# A least recently used cache relying on Ruby hash insertion order.
|
|
3
|
+
class LRUCache
|
|
4
|
+
@data: Hash[untyped, untyped]
|
|
5
|
+
|
|
6
|
+
@max_size: Integer
|
|
7
|
+
|
|
8
|
+
attr_reader max_size: Integer
|
|
9
|
+
|
|
10
|
+
def initialize: (?::Integer max_size) -> void
|
|
11
|
+
|
|
12
|
+
# Return the cached value or nil if _key_ does not exist.
|
|
13
|
+
def []: (untyped key) -> (nil | untyped)
|
|
14
|
+
|
|
15
|
+
def []=: (untyped key, untyped value) -> untyped
|
|
16
|
+
|
|
17
|
+
def length: () -> Integer
|
|
18
|
+
|
|
19
|
+
def keys: () -> Array[untyped]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module JSONP3
|
|
2
|
+
# The base class for all errors raised from this gem.
|
|
3
|
+
class Error < StandardError
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
module Path
|
|
7
|
+
class Error < JSONP3::Error
|
|
8
|
+
@token: t_token
|
|
9
|
+
|
|
10
|
+
@query: String
|
|
11
|
+
|
|
12
|
+
FULL_MESSAGE: bool
|
|
13
|
+
|
|
14
|
+
def initialize: (String msg, t_token token, String query) -> void
|
|
15
|
+
|
|
16
|
+
def detailed_message: (?highlight: bool, **untyped _kwargs) -> String
|
|
17
|
+
|
|
18
|
+
def full_message: (?highlight: bool, ?order: ::Symbol) -> (::String | untyped)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class SyntaxError < Error
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class TypeError < Error
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class NameError < Error
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class RecursionError < Error
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class Pointer
|
|
35
|
+
class Error < JSONP3::Error
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class IndexError < Error
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class SyntaxError < Error
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class TypeError < Error
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class Patch
|
|
49
|
+
class Error < JSONP3::Error
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class TestFailure < Error
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
module JSONP3
|
|
2
|
+
# A JSON Patch containing zero or more patch operations.
|
|
3
|
+
class Patch
|
|
4
|
+
@ops: Array[Op]
|
|
5
|
+
|
|
6
|
+
def self.apply!: (Array[Patch::Op | Hash[String, untyped]] ops, untyped value) -> untyped
|
|
7
|
+
|
|
8
|
+
# Base class for all JSON Patch operations
|
|
9
|
+
class Op
|
|
10
|
+
# Return the name of the patch operation.
|
|
11
|
+
def name: () -> String
|
|
12
|
+
|
|
13
|
+
# Apply the patch operation to _value_.
|
|
14
|
+
def apply!: (untyped _value, Integer _index) -> untyped
|
|
15
|
+
|
|
16
|
+
# Return a JSON-like representation of this patch operation.
|
|
17
|
+
def to_h: () -> untyped
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# The JSON Patch _add_ operation.
|
|
21
|
+
class OpAdd < Op
|
|
22
|
+
@pointer: JSONP3::Pointer
|
|
23
|
+
|
|
24
|
+
@value: untyped
|
|
25
|
+
|
|
26
|
+
# @param pointer [JSONP3::Pointer]
|
|
27
|
+
# @param value [JSON-like value]
|
|
28
|
+
def initialize: (JSONP3::Pointer pointer, untyped value) -> void
|
|
29
|
+
|
|
30
|
+
def name: () -> "add"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# The JSON Patch _remove_ operation.
|
|
34
|
+
class OpRemove < Op
|
|
35
|
+
@pointer: JSONP3::Pointer
|
|
36
|
+
|
|
37
|
+
# @param pointer [JSONP3::Pointer]
|
|
38
|
+
def initialize: (JSONP3::Pointer pointer) -> void
|
|
39
|
+
|
|
40
|
+
def name: () -> "remove"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# The JSON Patch _replace_ operation.
|
|
44
|
+
class OpReplace < Op
|
|
45
|
+
@pointer: JSONP3::Pointer
|
|
46
|
+
|
|
47
|
+
@value: untyped
|
|
48
|
+
|
|
49
|
+
# @param pointer [JSONP3::Pointer]
|
|
50
|
+
# @param value [JSON-like value]
|
|
51
|
+
def initialize: (JSONP3::Pointer pointer, untyped value) -> void
|
|
52
|
+
|
|
53
|
+
def name: () -> "replace"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# The JSON Patch _move_ operation.
|
|
57
|
+
class OpMove < Op
|
|
58
|
+
@from: JSONP3::Pointer
|
|
59
|
+
|
|
60
|
+
@pointer: JSONP3::Pointer
|
|
61
|
+
|
|
62
|
+
# @param from [JSONP3::Pointer]
|
|
63
|
+
# @param pointer [JSONP3::Pointer]
|
|
64
|
+
def initialize: (JSONP3::Pointer from, JSONP3::Pointer pointer) -> void
|
|
65
|
+
|
|
66
|
+
def name: () -> "move"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# The JSON Patch _copy_ operation.
|
|
70
|
+
class OpCopy < Op
|
|
71
|
+
@from: JSONP3::Pointer
|
|
72
|
+
|
|
73
|
+
@pointer: JSONP3::Pointer
|
|
74
|
+
|
|
75
|
+
# @param from [JSONP3::Pointer]
|
|
76
|
+
# @param pointer [JSONP3::Pointer]
|
|
77
|
+
def initialize: (JSONP3::Pointer from, JSONP3::Pointer pointer) -> void
|
|
78
|
+
|
|
79
|
+
def name: () -> "copy"
|
|
80
|
+
|
|
81
|
+
def deep_copy: (untyped obj) -> untyped
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# The JSON Patch _test_ operation.
|
|
85
|
+
class OpTest < Op
|
|
86
|
+
@pointer: JSONP3::Pointer
|
|
87
|
+
|
|
88
|
+
@value: untyped
|
|
89
|
+
|
|
90
|
+
# @param pointer [JSONP3::Pointer]
|
|
91
|
+
# @param value [JSON-like value]
|
|
92
|
+
def initialize: (JSONP3::Pointer pointer, untyped value) -> void
|
|
93
|
+
|
|
94
|
+
def name: () -> "test"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# @param ops [Array<Op>?]
|
|
98
|
+
def initialize: (?Array[Op | Hash[String, untyped]]? ops) -> void
|
|
99
|
+
|
|
100
|
+
# @param pointer [String | JSONP3::Pointer]
|
|
101
|
+
# @param value [JSON-like value]
|
|
102
|
+
# @return [self]
|
|
103
|
+
def add: (JSONP3::Pointer | String pointer, untyped value) -> self
|
|
104
|
+
|
|
105
|
+
# @param pointer [String | JSONP3::Pointer]
|
|
106
|
+
# @return [self]
|
|
107
|
+
def remove: (JSONP3::Pointer | String pointer) -> self
|
|
108
|
+
|
|
109
|
+
# @param pointer [String | JSONP3::Pointer]
|
|
110
|
+
# @param value [JSON-like value]
|
|
111
|
+
# @return [self]
|
|
112
|
+
def replace: (JSONP3::Pointer | String pointer, untyped value) -> self
|
|
113
|
+
|
|
114
|
+
# @param from [String | JSONP3::Pointer]
|
|
115
|
+
# @param pointer [String | JSONP3::Pointer]
|
|
116
|
+
# @return [self]
|
|
117
|
+
def move: (JSONP3::Pointer | String from, JSONP3::Pointer | String pointer) -> self
|
|
118
|
+
|
|
119
|
+
# @param from [String | JSONP3::Pointer]
|
|
120
|
+
# @param pointer [String | JSONP3::Pointer]
|
|
121
|
+
# @return [self]
|
|
122
|
+
def copy: (JSONP3::Pointer | String from, JSONP3::Pointer | String pointer) -> self
|
|
123
|
+
|
|
124
|
+
# @param pointer [String | JSONP3::Pointer]
|
|
125
|
+
# @param value [JSON-like value]
|
|
126
|
+
# @return [self]
|
|
127
|
+
def test: (JSONP3::Pointer | String pointer, untyped value) -> self
|
|
128
|
+
|
|
129
|
+
# Apply this patch to JSON-like value _value_.
|
|
130
|
+
def apply!: (untyped value) -> untyped
|
|
131
|
+
|
|
132
|
+
def to_a: () -> Array[untyped]
|
|
133
|
+
|
|
134
|
+
private
|
|
135
|
+
|
|
136
|
+
def ensure_pointer: (JSONP3::Pointer | String pointer, Symbol op, Integer index) -> JSONP3::Pointer
|
|
137
|
+
|
|
138
|
+
def build: (Array[Op | Hash[String, untyped]]) -> void
|
|
139
|
+
|
|
140
|
+
def op_pointer: (Hash[String, untyped] obj, String key, String op, Integer index) -> JSONP3::Pointer
|
|
141
|
+
|
|
142
|
+
def op_value: (Hash[String, untyped] obj, String key, String op, Integer index) -> untyped
|
|
143
|
+
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module JSONP3
|
|
2
|
+
module Path
|
|
3
|
+
# JSONPath configuration
|
|
4
|
+
#
|
|
5
|
+
# Configure an environment by inheriting from `Environment` and setting one
|
|
6
|
+
# or more constants and/or overriding {setup_function_extensions}.
|
|
7
|
+
class Environment
|
|
8
|
+
@function_extensions: Hash[String, FunctionExtension]
|
|
9
|
+
|
|
10
|
+
# The maximum integer allowed when selecting array items by index.
|
|
11
|
+
MAX_INT_INDEX: Numeric
|
|
12
|
+
|
|
13
|
+
# The minimum integer allowed when selecting array items by index.
|
|
14
|
+
MIN_INT_INDEX: Numeric
|
|
15
|
+
|
|
16
|
+
# The maximum number of arrays and hashes the recursive descent segment will
|
|
17
|
+
# traverse before raising a {JSONPathRecursionError}.
|
|
18
|
+
MAX_RECURSION_DEPTH: Integer
|
|
19
|
+
|
|
20
|
+
# One of the available implementations of the _name selector_.
|
|
21
|
+
#
|
|
22
|
+
# - {NameSelector} (the default) will select values from hashes using string keys.
|
|
23
|
+
# - {SymbolNameSelector} will select values from hashes using string or symbol keys.
|
|
24
|
+
#
|
|
25
|
+
# Implement your own name selector by inheriting from {NameSelector} and overriding
|
|
26
|
+
# `#resolve`.
|
|
27
|
+
NAME_SELECTOR: untyped
|
|
28
|
+
|
|
29
|
+
# An implementation of the _index selector_. The default implementation will
|
|
30
|
+
# select values from arrays only. Implement your own by inheriting from
|
|
31
|
+
# {IndexSelector} and overriding `#resolve`.
|
|
32
|
+
INDEX_SELECTOR: untyped
|
|
33
|
+
|
|
34
|
+
attr_accessor function_extensions: Hash[String, FunctionExtension]
|
|
35
|
+
|
|
36
|
+
def initialize: () -> void
|
|
37
|
+
|
|
38
|
+
# Prepare JSONPath expression _query_ for repeated application.
|
|
39
|
+
# @param query [String]
|
|
40
|
+
# @return [Query]
|
|
41
|
+
def compile: (String query) -> Query
|
|
42
|
+
|
|
43
|
+
# Apply JSONPath expression _query_ to _value_.
|
|
44
|
+
# @param query [String] the JSONPath expression
|
|
45
|
+
# @param value [JSON-like data] the target JSON "document"
|
|
46
|
+
# @return [Array<JSONPath>]
|
|
47
|
+
def find: (String query, untyped value) -> JSONP3::Path::NodeList
|
|
48
|
+
|
|
49
|
+
# Apply JSONPath expression _query_ to _value_.
|
|
50
|
+
# @param query [String] the JSONPath expression
|
|
51
|
+
# @param value [JSON-like data] the target JSON "document"
|
|
52
|
+
# @return [Enumerable<Query>]
|
|
53
|
+
def find_enum: (String query, untyped value) -> Enumerable[JSONP3::Path::Node]
|
|
54
|
+
|
|
55
|
+
# Apply JSONPath expression _query_ to _value_ an return the first
|
|
56
|
+
# available node.
|
|
57
|
+
# @param query [String] the JSONPath expression
|
|
58
|
+
# @param value [JSON-like data] the target JSON "document"
|
|
59
|
+
# @return [Node | nil]
|
|
60
|
+
def match: (String path, untyped value) -> (JSONP3::Path::Node | nil)
|
|
61
|
+
|
|
62
|
+
# Apply JSONPath expression _query_ to _value_ an return `true` if there's at
|
|
63
|
+
# least one node, or nil if there were no matches.
|
|
64
|
+
# @param query [String] the JSONPath expression
|
|
65
|
+
# @param value [JSON-like data] the target JSON "document"
|
|
66
|
+
# @return [bool]
|
|
67
|
+
def match?: (String path, untyped value) -> bool
|
|
68
|
+
|
|
69
|
+
# Apply JSONPath expression _query_ to _value_ an return the first
|
|
70
|
+
# available node, or nil if there were no matches.
|
|
71
|
+
# @param query [String] the JSONPath expression
|
|
72
|
+
# @param value [JSON-like data] the target JSON "document"
|
|
73
|
+
# @return [Node | nil]
|
|
74
|
+
def first: (untyped path, untyped value) -> (JSONP3::Path::Node | nil)
|
|
75
|
+
|
|
76
|
+
# Override this function to configure JSONPath function extensions.
|
|
77
|
+
# By default, only the standard functions described in RFC 9535 are enabled.
|
|
78
|
+
def setup_function_extensions: () -> untyped
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|