json_p3 1.0.0 → 1.0.1
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/CHANGELOG.md +56 -42
- data/certs/jgrp.pem +21 -21
- data/lib/json_p3/patch/op.rb +27 -0
- data/lib/json_p3/patch/op_add.rb +2 -16
- data/lib/json_p3/patch/op_copy.rb +4 -16
- data/lib/json_p3/patch/op_move.rb +5 -15
- data/lib/json_p3/patch/op_remove.rb +1 -1
- data/lib/json_p3/patch/op_replace.rb +1 -1
- data/lib/json_p3/path/lexer.rb +6 -2
- data/lib/json_p3/path/parser.rb +4 -3
- data/lib/json_p3/path/selector.rb +21 -16
- data/lib/json_p3/path/unescape.rb +0 -8
- data/lib/json_p3/version.rb +1 -1
- data/sig/json_p3/patch.rbs +7 -0
- data/sig/json_p3/path/selector.rbs +3 -0
- data.tar.gz.sig +0 -0
- metadata +22 -22
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 506b34d62097639d18aae756967a490cacd9d810ffa49361d9556149d83c8802
|
|
4
|
+
data.tar.gz: 4a5565093f304714305a7664a6f7a868aa70c0a9aa8c99a67c9ff067166edfcf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a21a879a120bd3209e2066ad26d1cceac3e44686bf5fd4f5ecb939f4094156a9ee25c17d099113911dadba34dc0a9c2ff44d28c7d8680f29682ef9993f30b874
|
|
7
|
+
data.tar.gz: 49668d5a557ec389d644e5a6965f3433ac20165d724868551fb1fbda5b1c99dcab92b7bbf296ecabc2694c50ff76166d76a5e562b60c54afe0770458b5d2ff87
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -1,51 +1,65 @@
|
|
|
1
|
+
## [1.0.1] - 2026-10-18
|
|
2
|
+
|
|
3
|
+
- Fixed the JSON Patch `move` operation overwriting the item at its target array index instead of inserting before it, which corrupted arrays when reordering their items. [RFC 6902 section 4.4](https://datatracker.ietf.org/doc/html/rfc6902#section-4.4) defines `move` as a `remove` followed by an `add`, and [section 4.1](https://datatracker.ietf.org/doc/html/rfc6902#section-4.1) says that when an `add` targets an array index "a new value is inserted into the array at the specified index".
|
|
4
|
+
- Fixed the JSON Patch `add` operation rejecting an array index equal to the length of the array. [RFC 6902 section 4.1](https://datatracker.ietf.org/doc/html/rfc6902#section-4.1) only requires that the specified index "MUST NOT be greater than the number of elements in the array", so an index equal to the length is valid and appends to the array.
|
|
5
|
+
- Fixed the JSON Patch `move` and `copy` operations padding an array with `nil` when their target index was past the end of the array. Both are defined in terms of `add` (RFC 6902 [section 4.4](https://datatracker.ietf.org/doc/html/rfc6902#section-4.4) and [section 4.5](https://datatracker.ietf.org/doc/html/rfc6902#section-4.5)), whose index "MUST NOT be greater than the number of elements in the array" ([section 4.1](https://datatracker.ietf.org/doc/html/rfc6902#section-4.1)). Under [section 5](https://datatracker.ietf.org/doc/html/rfc6902#section-5), violating a normative requirement means the patch "SHALL NOT be deemed successful", so they now raise a `JSONP3::Patch::Error`, as `add` does.
|
|
6
|
+
- Fixed the JSON Patch `move` and `copy` operations replacing the whole document with the moved or copied value when the parent of the target does not exist. [RFC 6902 section 4.1](https://datatracker.ietf.org/doc/html/rfc6902#section-4.1) says the object or array being added to "does need to exist, and it remains an error for that not to be the case", and `move` and `copy` inherit that from `add` ([section 4.4](https://datatracker.ietf.org/doc/html/rfc6902#section-4.4) and [section 4.5](https://datatracker.ietf.org/doc/html/rfc6902#section-4.5)). They now raise a `JSONP3::Patch::Error`.
|
|
7
|
+
- Fixed the JSON Patch `move` operation silently discarding the moved value when the parent of the target is neither an array nor an object. [RFC 6902 section 4.1](https://datatracker.ietf.org/doc/html/rfc6902#section-4.1) says the target location "MUST reference one of" the document root, a member of an existing object or an element of an existing array, and [section 5](https://datatracker.ietf.org/doc/html/rfc6902#section-5) requires an operation that cannot succeed to fail the patch. It now raises a `JSONP3::Patch::Error`, as `add` and `copy` already did.
|
|
8
|
+
- Fixed the JSON Patch `copy` operation not copying the value when appending it to an array with `-`, so the copy and its source shared nested arrays and objects. [RFC 6902 section 4.5](https://datatracker.ietf.org/doc/html/rfc6902#section-4.5) defines `copy` as an `add` of the value at `from`, which leaves the document with two independent values. With the shared objects, a later operation on one changed the other, and copying an array to its own end made the array contain itself.
|
|
9
|
+
- Fixed JSON Patch operations targeting an object member whose name is a non-negative integer, like `/foo/1`. `add`, `copy` and `move` wrote the value under an integer key instead of the member name, duplicating the member when it already existed, `replace` added an integer key alongside the existing member, `remove` did nothing, and `move` left its source member in place. Under [RFC 6901 section 4](https://datatracker.ietf.org/doc/html/rfc6901#section-4), when a reference token is applied to an object, "the new referenced value is the object member with the name identified by the reference token". A token is only read as an array index when it is applied to an array. [RFC 8259 section 4](https://datatracker.ietf.org/doc/html/rfc8259#section-4) says "A name is a string" and "The names within an object SHOULD be unique", so a second key for the same name produced JSON with duplicate member names.
|
|
10
|
+
- Fixed trailing comma detection in JSONPath bracketed segments. Previously we failed to consume whitespace after a comma and before checking for `]`.
|
|
11
|
+
- Fixed JSONPath `\u` escape sequence rejection of code points less than or equal to 0x1F. The spec requires us to reject literals of 0x1F or lower, not escape sequences.
|
|
12
|
+
- Fixed the JSONPath shorthand name selector to accept the full range of allow Unicode code points.
|
|
13
|
+
- Fixed the JSONPath slice selector when a start index equal to the target array's length and default end and step values would result in selecting the last value in the array.
|
|
14
|
+
|
|
1
15
|
## [1.0.0] - 2026-04-21
|
|
2
16
|
|
|
3
17
|
This major release includes breaking changes. No new features have been added.
|
|
4
18
|
|
|
5
19
|
- Changed the JSONPath tokenizer and parser. The new parser is faster and more JIT friendly.
|
|
6
20
|
- Changed our module and class layout to better separate JSONPath, JSON Pointer and JSON Patch, and to remove "stuttering". For example, previously we had `JSONP3::JSONPathEnvironment` and `JSONP3::JSONPathNode`. Now we have `JSONP3::Path::Environment` and `JSONP3::Path:Node`. This ASCII tree view show our new module and class hierarchy.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
module JSONP3
|
|
24
|
+
├── class Error < StandardError
|
|
25
|
+
│
|
|
26
|
+
├── module Path # JSONPath (RFC 9535)
|
|
27
|
+
│ ├── class Environment
|
|
28
|
+
│ ├── class Query
|
|
29
|
+
│ ├── class Node
|
|
30
|
+
│ ├── class NodeList
|
|
31
|
+
│ ├── class Error < JSONP3::Error
|
|
32
|
+
│ │ ├── class SyntaxError
|
|
33
|
+
│ │ ├── class TypeError
|
|
34
|
+
│ │ ├── class NameError
|
|
35
|
+
│ │ └── class RecursionError
|
|
36
|
+
│ ├── def self.find
|
|
37
|
+
│ ├── def self.find_enum
|
|
38
|
+
│ ├── def self.compile
|
|
39
|
+
│ ├── def self.match
|
|
40
|
+
│ ├── def self.match?
|
|
41
|
+
│ └── def self.first
|
|
42
|
+
│
|
|
43
|
+
├── class Pointer # JSON Pointer (RFC 6901)
|
|
44
|
+
│ ├── class Error < JSONP3::Error
|
|
45
|
+
│ │ ├── class IndexError
|
|
46
|
+
│ │ ├── class SyntaxError
|
|
47
|
+
│ │ └── class TypeError
|
|
48
|
+
│ └── def self.resolve
|
|
49
|
+
│
|
|
50
|
+
└── class Patch # JSON Patch (RFC 6902)
|
|
51
|
+
├── class OpAdd
|
|
52
|
+
├── class OpCopy
|
|
53
|
+
├── class OpMove
|
|
54
|
+
├── class OpRemove
|
|
55
|
+
├── class OpReplace
|
|
56
|
+
├── class OpTest
|
|
57
|
+
├── class Error < JSONP3::Error
|
|
58
|
+
│ └── class TestFailure
|
|
59
|
+
└── def !self.apply
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Note that top-level convenience methods - like `JSONP3.find` and `JSONP3.compile` - are unchanged. Most dependent projects should only need to change error class names.
|
|
49
63
|
|
|
50
64
|
- Renamed `JSONP3::JSONPath` to `JSONP3::Path::Query`.
|
|
51
65
|
- Renamed `JSONP3::RecursiveDescentSegment` to `JSONP3::Path::DescendantSegment` to better match the spec.
|
data/certs/jgrp.pem
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
-----BEGIN CERTIFICATE-----
|
|
2
2
|
MIIEhTCCAu2gAwIBAgIBATANBgkqhkiG9w0BAQsFADBEMRYwFAYDVQQDDA1qYW1l
|
|
3
3
|
c2dyLnByaW9yMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
|
|
4
|
-
|
|
4
|
+
FgNjb20wHhcNMjYxMDE4MTMzMTExWhcNMjcxMDE4MTMzMTExWjBEMRYwFAYDVQQD
|
|
5
5
|
DA1qYW1lc2dyLnByaW9yMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJ
|
|
6
|
-
k/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
AaOBgTB/
|
|
16
|
-
|
|
6
|
+
k/IsZAEZFgNjb20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDAXkrS
|
|
7
|
+
W5E5Ts892bcQSSt/+RoE6T7yf6rWBxWs6PSNksUM05toEX7Mmsq+u5hJ2oVit9Tp
|
|
8
|
+
/Gvpq4eANMv95vQnLmiT+1J3YauckaTB0TaArf77ytdiOxlfgYRt0Di6QmZVkinR
|
|
9
|
+
BDA9qTcsuwmia5IBG6mcjpmAoiNeBtz6jv/PqCYBitnJEW0dpaqd7r3Lmzh9B562
|
|
10
|
+
Z/kGD8nmVpA6Wj/i5PjBlhMfQ7TRdAZi4xji96gAoFo4v3JY8r8baH6ww/uT4cFC
|
|
11
|
+
O0vIh2FpSyrWT/nAqEqfjHl5XShLTUdDbcTyl5rnU1lZr66A0gl4x/gKYglYsRfO
|
|
12
|
+
xo9TPH2P0G3U+iTI/a0jeNlXi9cxZMw1LaUChB+rI9qa/xpvOYUb76pu7BJmtpp/
|
|
13
|
+
QyBHujNa0VCtCmfWJnVaR6JNPKza5VP38BPvS1YriXDnkLAxZ4ruAXrTtneQyemP
|
|
14
|
+
4umgDSJ9ESXdNfgZkGcXsNmXSU7vLYZAp4OajBhUp5hnRSw4y6HWKt8oG2kCAwEA
|
|
15
|
+
AaOBgTB/MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBROcgTGvg8n
|
|
16
|
+
3d5QbkQz4JzlE7Jk0TAiBgNVHREEGzAZgRdqYW1lc2dyLnByaW9yQGdtYWlsLmNv
|
|
17
17
|
bTAiBgNVHRIEGzAZgRdqYW1lc2dyLnByaW9yQGdtYWlsLmNvbTANBgkqhkiG9w0B
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
AQsFAAOCAYEAZLTr3Z6ZNmlI+AT9ci2wCC7A74OVNME8eZaqcBxGuXE/9jWycIQX
|
|
19
|
+
RTggqZcofJpgKNMFIrelQDCa/Jf3fbCtdVfbcEb6vITlr7Zt/M/mHzu/QjjIFpmT
|
|
20
|
+
gTXlP8APjoQxWaRrhOAm5nbgwYKrOPdLtBu3uzN3PAhbZQlLHyM49bWSux75Ibxy
|
|
21
|
+
nL0cYGR05H3ym7U9XRRuEExHJ0gCW67CwchWNav0yEgeko5Sn3BSjMISBdy9jF5c
|
|
22
|
+
bJgFKiVQFTN+5+uHtBUu5YrtCgsMTgr09g6DgpUUlALHOyg7+XEp/MeqZqE3g5Qu
|
|
23
|
+
JubJmxfW7PrLuyBLkHeIxpvVdpORTaH3/U5qb45XPJ1z2IHC91IlBIoFSOsDrCrL
|
|
24
|
+
kPjfyWVsL/uWyRIDnXRoTTepSBND6NmHrGWuTiYDB7r/Yeqj714R6GF1qe2jZlDW
|
|
25
|
+
yE12qcU40zRwg3LPrEwjuaF4Lo29G666PBWxGcLbakvRUDuO5GG5rqJydmX2KV/J
|
|
26
|
+
NlOr4XEE+abN
|
|
27
27
|
-----END CERTIFICATE-----
|
data/lib/json_p3/patch/op.rb
CHANGED
|
@@ -18,6 +18,33 @@ module JSONP3
|
|
|
18
18
|
def to_h
|
|
19
19
|
raise "JSON Patch operations must implement #to_h"
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
# Add _obj_ to _parent_ at _target_ following the semantics of the JSON
|
|
25
|
+
# Patch _add_ operation: insert into arrays, set object members.
|
|
26
|
+
def add_member(parent, target, obj, index)
|
|
27
|
+
if parent.is_a?(Array)
|
|
28
|
+
if target == "-"
|
|
29
|
+
parent << obj
|
|
30
|
+
elsif target.is_a?(Integer) && target <= parent.length
|
|
31
|
+
parent.insert(target, obj)
|
|
32
|
+
else
|
|
33
|
+
raise JSONP3::Patch::Error, "index out of range (#{name}:#{index})"
|
|
34
|
+
end
|
|
35
|
+
elsif parent.is_a?(Hash)
|
|
36
|
+
parent[member_key(parent, target)] = obj
|
|
37
|
+
else
|
|
38
|
+
raise JSONP3::Patch::Error, "unexpected operation on #{parent.class} (#{name}:#{index})"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Return the key of _parent_ identified by pointer token _target_.
|
|
43
|
+
# Pointer tokens that look like array indices are integers, but object
|
|
44
|
+
# member names are strings.
|
|
45
|
+
def member_key(parent, target)
|
|
46
|
+
parent.key?(target) ? target : target.to_s
|
|
47
|
+
end
|
|
21
48
|
end
|
|
22
49
|
end
|
|
23
50
|
end
|
data/lib/json_p3/patch/op_add.rb
CHANGED
|
@@ -17,7 +17,7 @@ module JSONP3
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def apply!(value, index)
|
|
20
|
-
parent,
|
|
20
|
+
parent, _obj = @pointer.resolve_with_parent(value)
|
|
21
21
|
return @value if parent == JSONP3::Pointer::UNDEFINED && @pointer.tokens.empty?
|
|
22
22
|
|
|
23
23
|
if parent == JSONP3::Pointer::UNDEFINED
|
|
@@ -25,21 +25,7 @@ module JSONP3
|
|
|
25
25
|
"no such property or item '#{@pointer.parent}' (#{name}:#{index})"
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
if parent.is_a?(Array)
|
|
30
|
-
if obj == JSONP3::Pointer::UNDEFINED
|
|
31
|
-
raise JSONP3::Patch::Error, "index out of range (#{name}:#{index})" unless target == "-"
|
|
32
|
-
|
|
33
|
-
parent << @value
|
|
34
|
-
else
|
|
35
|
-
parent.insert(target.to_i, @value)
|
|
36
|
-
end
|
|
37
|
-
elsif parent.is_a?(Hash)
|
|
38
|
-
parent[target] = @value
|
|
39
|
-
else
|
|
40
|
-
raise JSONP3::Patch::Error, "unexpected operation on #{parent.class} (#{name}:#{index})"
|
|
41
|
-
end
|
|
42
|
-
|
|
28
|
+
add_member(parent, @pointer.tokens.last, @value, index)
|
|
43
29
|
value
|
|
44
30
|
end
|
|
45
31
|
|
|
@@ -26,27 +26,15 @@ module JSONP3
|
|
|
26
26
|
|
|
27
27
|
# Find the parent of the destination pointer.
|
|
28
28
|
dest_parent, _dest_obj = @pointer.resolve_with_parent(value)
|
|
29
|
-
return deep_copy(source_obj) if
|
|
29
|
+
return deep_copy(source_obj) if @pointer.tokens.empty?
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
if dest_target == JSONP3::Pointer::UNDEFINED
|
|
31
|
+
if dest_parent == JSONP3::Pointer::UNDEFINED
|
|
33
32
|
raise JSONP3::Patch::Error,
|
|
34
|
-
"
|
|
33
|
+
"no such property or item '#{@pointer.parent}' (#{name}:#{index})"
|
|
35
34
|
end
|
|
36
35
|
|
|
37
36
|
# Write the source value to the destination.
|
|
38
|
-
|
|
39
|
-
if dest_target == "-"
|
|
40
|
-
dest_parent << source_obj
|
|
41
|
-
else
|
|
42
|
-
dest_parent.insert(dest_target.to_i, deep_copy(source_obj))
|
|
43
|
-
end
|
|
44
|
-
elsif dest_parent.is_a?(Hash)
|
|
45
|
-
dest_parent[dest_target] = deep_copy(source_obj)
|
|
46
|
-
else
|
|
47
|
-
raise JSONP3::Patch::Error, "unexpected operation on #{dest_parent.class} (#{name}:#{index})"
|
|
48
|
-
end
|
|
49
|
-
|
|
37
|
+
add_member(dest_parent, @pointer.tokens.last, deep_copy(source_obj), index)
|
|
50
38
|
value
|
|
51
39
|
end
|
|
52
40
|
|
|
@@ -39,30 +39,20 @@ module JSONP3
|
|
|
39
39
|
if source_parent.is_a?(Array)
|
|
40
40
|
source_parent.delete_at(source_target.to_i)
|
|
41
41
|
elsif source_parent.is_a?(Hash)
|
|
42
|
-
source_parent.delete(source_target)
|
|
42
|
+
source_parent.delete(member_key(source_parent, source_target))
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
# Find the parent of the destination pointer.
|
|
46
46
|
dest_parent, _dest_obj = @pointer.resolve_with_parent(value)
|
|
47
|
-
return source_obj if
|
|
47
|
+
return source_obj if @pointer.tokens.empty?
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
if dest_target == JSONP3::Pointer::UNDEFINED
|
|
49
|
+
if dest_parent == JSONP3::Pointer::UNDEFINED
|
|
51
50
|
raise JSONP3::Patch::Error,
|
|
52
|
-
"
|
|
51
|
+
"no such property or item '#{@pointer.parent}' (#{name}:#{index})"
|
|
53
52
|
end
|
|
54
53
|
|
|
55
54
|
# Write the source value to the destination.
|
|
56
|
-
|
|
57
|
-
if dest_target == "-"
|
|
58
|
-
dest_parent << source_obj
|
|
59
|
-
else
|
|
60
|
-
dest_parent[dest_target.to_i] = source_obj
|
|
61
|
-
end
|
|
62
|
-
elsif dest_parent.is_a?(Hash)
|
|
63
|
-
dest_parent[dest_target] = source_obj
|
|
64
|
-
end
|
|
65
|
-
|
|
55
|
+
add_member(dest_parent, @pointer.tokens.last, source_obj, index)
|
|
66
56
|
value
|
|
67
57
|
end
|
|
68
58
|
|
|
@@ -40,7 +40,7 @@ module JSONP3
|
|
|
40
40
|
elsif parent.is_a?(Hash)
|
|
41
41
|
raise JSONP3::Patch::Error, "no property to remove (#{name}:#{index})" if obj == JSONP3::Pointer::UNDEFINED
|
|
42
42
|
|
|
43
|
-
parent.delete(target)
|
|
43
|
+
parent.delete(member_key(parent, target))
|
|
44
44
|
else
|
|
45
45
|
raise JSONP3::Patch::Error, "unexpected operation on #{parent.class} (#{name}:#{index})"
|
|
46
46
|
end
|
|
@@ -38,7 +38,7 @@ module JSONP3
|
|
|
38
38
|
elsif parent.is_a?(Hash)
|
|
39
39
|
raise JSONP3::Patch::Error, "no property to replace (#{name}:#{index})" if obj == JSONP3::Pointer::UNDEFINED
|
|
40
40
|
|
|
41
|
-
parent[target] = @value
|
|
41
|
+
parent[member_key(parent, target)] = @value
|
|
42
42
|
else
|
|
43
43
|
raise JSONP3::Patch::Error, "unexpected operation on #{parent.class} (#{name}:#{index})"
|
|
44
44
|
end
|
data/lib/json_p3/path/lexer.rb
CHANGED
|
@@ -194,7 +194,11 @@ module JSONP3
|
|
|
194
194
|
end
|
|
195
195
|
|
|
196
196
|
def self.name_first?(ch)
|
|
197
|
-
(ch >= 65 && ch <= 90) ||
|
|
197
|
+
(ch >= 65 && ch <= 90) ||
|
|
198
|
+
(ch >= 97 && ch <= 122) ||
|
|
199
|
+
ch == 95 ||
|
|
200
|
+
(ch >= 0x80 && ch <= 0xD7FF) ||
|
|
201
|
+
(ch >= 0xE000 && ch <= 0x10FFFF)
|
|
198
202
|
end
|
|
199
203
|
|
|
200
204
|
def self.name_ch?(ch)
|
|
@@ -202,7 +206,7 @@ module JSONP3
|
|
|
202
206
|
(ch >= 65 && ch <= 90) ||
|
|
203
207
|
(ch >= 97 && ch <= 122) ||
|
|
204
208
|
ch == 95 ||
|
|
205
|
-
(ch >= 0x80 && ch <=
|
|
209
|
+
(ch >= 0x80 && ch <= 0x10FFFF)
|
|
206
210
|
end
|
|
207
211
|
|
|
208
212
|
def self.number_ch?(ch)
|
data/lib/json_p3/path/parser.rb
CHANGED
|
@@ -237,11 +237,12 @@ module JSONP3
|
|
|
237
237
|
when :token_rbracket
|
|
238
238
|
break
|
|
239
239
|
else
|
|
240
|
-
eat(:token_comma)
|
|
240
|
+
comma_token = eat(:token_comma)
|
|
241
|
+
skip(:token_trivia)
|
|
241
242
|
if peek.first == :token_rbracket
|
|
242
243
|
raise SyntaxError.new(
|
|
243
244
|
"unexpected trailing comma",
|
|
244
|
-
|
|
245
|
+
comma_token,
|
|
245
246
|
@query
|
|
246
247
|
)
|
|
247
248
|
end
|
|
@@ -364,7 +365,7 @@ module JSONP3
|
|
|
364
365
|
func = @env.function_extensions[name]
|
|
365
366
|
|
|
366
367
|
unless func
|
|
367
|
-
raise
|
|
368
|
+
raise NameError.new(
|
|
368
369
|
"unknown function extension #{name}",
|
|
369
370
|
token,
|
|
370
371
|
@query
|
|
@@ -199,23 +199,15 @@ module JSONP3
|
|
|
199
199
|
length = node.value.length
|
|
200
200
|
return [] if length.zero? || @step.zero?
|
|
201
201
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
normalized_stop = if @stop.nil?
|
|
211
|
-
@step.negative? ? -1 : length
|
|
212
|
-
elsif @stop&.negative?
|
|
213
|
-
[length + (@stop || raise), -1].max
|
|
214
|
-
else
|
|
215
|
-
[@stop || raise, length].min
|
|
216
|
-
end
|
|
202
|
+
if step.positive?
|
|
203
|
+
norm_start = normalized_index(@start, 0, length, @step)
|
|
204
|
+
norm_end = normalized_index(@stop, length, length, @step)
|
|
205
|
+
else
|
|
206
|
+
norm_start = normalized_index(@start, length - 1, length, @step)
|
|
207
|
+
norm_end = normalized_index(@stop, -1, length, @step)
|
|
208
|
+
end
|
|
217
209
|
|
|
218
|
-
(
|
|
210
|
+
(norm_start...norm_end).step(@step).map { |i| node.new_child(node.value[i], i) }
|
|
219
211
|
end
|
|
220
212
|
|
|
221
213
|
def to_s
|
|
@@ -238,6 +230,19 @@ module JSONP3
|
|
|
238
230
|
def hash
|
|
239
231
|
[@start, @stop, @step, @token].hash
|
|
240
232
|
end
|
|
233
|
+
|
|
234
|
+
private
|
|
235
|
+
|
|
236
|
+
#: (Integer?, Integer, Integer, Integer) -> Integer
|
|
237
|
+
def normalized_index(num, default, length, step)
|
|
238
|
+
return default if num.nil?
|
|
239
|
+
|
|
240
|
+
if num.negative?
|
|
241
|
+
return step.negative? ? [num + length, -1].max : [num + length, 0].max
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
step.negative? ? [num, length - 1].min : [num, length].min
|
|
245
|
+
end
|
|
241
246
|
end
|
|
242
247
|
|
|
243
248
|
# Select array elements or hash values according to a filter expression.
|
data/lib/json_p3/version.rb
CHANGED
data/sig/json_p3/patch.rbs
CHANGED
|
@@ -15,6 +15,13 @@ module JSONP3
|
|
|
15
15
|
|
|
16
16
|
# Return a JSON-like representation of this patch operation.
|
|
17
17
|
def to_h: () -> untyped
|
|
18
|
+
|
|
19
|
+
# Add _obj_ to _parent_ at _target_ following the semantics of the JSON
|
|
20
|
+
# Patch _add_ operation: insert into arrays, set object members.
|
|
21
|
+
private def add_member: (untyped parent, String | Integer target, untyped obj, Integer index) -> void
|
|
22
|
+
|
|
23
|
+
# Return the key of _parent_ identified by pointer token _target_.
|
|
24
|
+
private def member_key: (Hash[untyped, untyped] parent, String | Integer target) -> (String | Integer)
|
|
18
25
|
end
|
|
19
26
|
|
|
20
27
|
# The JSON Patch _add_ operation.
|
|
@@ -29,6 +29,9 @@ module JSONP3
|
|
|
29
29
|
alias eql? ==
|
|
30
30
|
|
|
31
31
|
def hash: () -> Integer
|
|
32
|
+
|
|
33
|
+
#: (Integer?, Integer, Integer, Integer) -> Integer
|
|
34
|
+
def normalized_index: (Integer? num, Integer default, Integer length, Integer step) -> Integer
|
|
32
35
|
end
|
|
33
36
|
|
|
34
37
|
# The name selector select values from hashes given a key.
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: json_p3
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- James Prior
|
|
@@ -11,29 +11,29 @@ cert_chain:
|
|
|
11
11
|
-----BEGIN CERTIFICATE-----
|
|
12
12
|
MIIEhTCCAu2gAwIBAgIBATANBgkqhkiG9w0BAQsFADBEMRYwFAYDVQQDDA1qYW1l
|
|
13
13
|
c2dyLnByaW9yMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
|
|
14
|
-
|
|
14
|
+
FgNjb20wHhcNMjYxMDE4MTMzMTExWhcNMjcxMDE4MTMzMTExWjBEMRYwFAYDVQQD
|
|
15
15
|
DA1qYW1lc2dyLnByaW9yMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJ
|
|
16
|
-
k/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
AaOBgTB/
|
|
26
|
-
|
|
16
|
+
k/IsZAEZFgNjb20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDAXkrS
|
|
17
|
+
W5E5Ts892bcQSSt/+RoE6T7yf6rWBxWs6PSNksUM05toEX7Mmsq+u5hJ2oVit9Tp
|
|
18
|
+
/Gvpq4eANMv95vQnLmiT+1J3YauckaTB0TaArf77ytdiOxlfgYRt0Di6QmZVkinR
|
|
19
|
+
BDA9qTcsuwmia5IBG6mcjpmAoiNeBtz6jv/PqCYBitnJEW0dpaqd7r3Lmzh9B562
|
|
20
|
+
Z/kGD8nmVpA6Wj/i5PjBlhMfQ7TRdAZi4xji96gAoFo4v3JY8r8baH6ww/uT4cFC
|
|
21
|
+
O0vIh2FpSyrWT/nAqEqfjHl5XShLTUdDbcTyl5rnU1lZr66A0gl4x/gKYglYsRfO
|
|
22
|
+
xo9TPH2P0G3U+iTI/a0jeNlXi9cxZMw1LaUChB+rI9qa/xpvOYUb76pu7BJmtpp/
|
|
23
|
+
QyBHujNa0VCtCmfWJnVaR6JNPKza5VP38BPvS1YriXDnkLAxZ4ruAXrTtneQyemP
|
|
24
|
+
4umgDSJ9ESXdNfgZkGcXsNmXSU7vLYZAp4OajBhUp5hnRSw4y6HWKt8oG2kCAwEA
|
|
25
|
+
AaOBgTB/MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBROcgTGvg8n
|
|
26
|
+
3d5QbkQz4JzlE7Jk0TAiBgNVHREEGzAZgRdqYW1lc2dyLnByaW9yQGdtYWlsLmNv
|
|
27
27
|
bTAiBgNVHRIEGzAZgRdqYW1lc2dyLnByaW9yQGdtYWlsLmNvbTANBgkqhkiG9w0B
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
28
|
+
AQsFAAOCAYEAZLTr3Z6ZNmlI+AT9ci2wCC7A74OVNME8eZaqcBxGuXE/9jWycIQX
|
|
29
|
+
RTggqZcofJpgKNMFIrelQDCa/Jf3fbCtdVfbcEb6vITlr7Zt/M/mHzu/QjjIFpmT
|
|
30
|
+
gTXlP8APjoQxWaRrhOAm5nbgwYKrOPdLtBu3uzN3PAhbZQlLHyM49bWSux75Ibxy
|
|
31
|
+
nL0cYGR05H3ym7U9XRRuEExHJ0gCW67CwchWNav0yEgeko5Sn3BSjMISBdy9jF5c
|
|
32
|
+
bJgFKiVQFTN+5+uHtBUu5YrtCgsMTgr09g6DgpUUlALHOyg7+XEp/MeqZqE3g5Qu
|
|
33
|
+
JubJmxfW7PrLuyBLkHeIxpvVdpORTaH3/U5qb45XPJ1z2IHC91IlBIoFSOsDrCrL
|
|
34
|
+
kPjfyWVsL/uWyRIDnXRoTTepSBND6NmHrGWuTiYDB7r/Yeqj714R6GF1qe2jZlDW
|
|
35
|
+
yE12qcU40zRwg3LPrEwjuaF4Lo29G666PBWxGcLbakvRUDuO5GG5rqJydmX2KV/J
|
|
36
|
+
NlOr4XEE+abN
|
|
37
37
|
-----END CERTIFICATE-----
|
|
38
38
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
39
39
|
dependencies: []
|
metadata.gz.sig
CHANGED
|
Binary file
|