Skip to content

Commit 08049fa

Browse files
author
Mike McCabe
committed
Experimental 'append' op for adding an array to the end of an existing array (with '-')
1 parent 15926a2 commit 08049fa

File tree

2 files changed

+34
-101
lines changed

2 files changed

+34
-101
lines changed

JsonPatch.inc

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,14 @@ class JsonPatch
102102
. json_encode($patch));
103103
}
104104
if (!in_array($op, array('add', 'remove', 'replace',
105-
'move', 'copy', 'test')))
105+
'move', 'copy', 'test', 'append')))
106106
{
107107
throw new JsonPatchException("Unrecognized op '$op' in "
108108
. json_encode($patch));
109109
}
110110

111111
$parts = self::decompose_pointer($path);
112-
if (in_array($op, Array('test', 'add', 'replace')))
112+
if (in_array($op, Array('test', 'add', 'replace', 'append')))
113113
{
114114
if (!array_key_exists('value', $patch))
115115
{
@@ -134,6 +134,11 @@ class JsonPatch
134134
$doc = self::do_op($doc, $op, $path, $parts, $value,
135135
$simplexml_mode);
136136
}
137+
if ($op === 'append')
138+
{
139+
$doc = self::do_op($doc, $op, $path, $parts, $value,
140+
$simplexml_mode);
141+
}
137142
else if ($op == 'replace')
138143
{
139144
$doc = self::do_op($doc, $op, $path, $parts, $value,
@@ -520,7 +525,7 @@ class JsonPatch
520525
if (!self::is_associative($doc)) // N.B. returns false for empty arrays
521526
{
522527
if (count($doc) && !self::is_index($part)
523-
&& !($part == '-' && $op == 'add'))
528+
&& !($part == '-' && ($op == 'add' || $op == 'append')))
524529
{
525530
throw new JsonPatchException("Non-array key '$part' used on array");
526531
}
@@ -536,14 +541,21 @@ class JsonPatch
536541
}
537542
}
538543

539-
if ($op == 'add')
544+
if ($op == 'add' || $op == 'append')
540545
{
541546
if (!self::is_associative($doc)
542547
&& (self::is_index($part) || $part == '-'))
543548
{
544549
// If index is '-', use array length
545550
$index = ($part == '-') ? count($doc) : $part;
546-
array_splice($doc, $index, 0, Array($value));
551+
if ($op == 'append')
552+
{
553+
array_splice($doc, $index, 0, $value);
554+
}
555+
else
556+
{
557+
array_splice($doc, $index, 0, Array($value));
558+
}
547559
}
548560
else
549561
{

local_tests.json

Lines changed: 17 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,6 @@
44
"patch": [ { "op": "add", "path": "/1", "value": 2 } ],
55
"expected": { "foo": 1, "1": 2 } },
66

7-
{ "comment": "missing 'value' parameter to add",
8-
"doc": [ 1 ],
9-
"patch": [ { "op": "add", "path": "/-" } ],
10-
"error": "missing 'value' parameter" },
11-
12-
{ "comment": "missing 'value' parameter to replace",
13-
"doc": [ 1 ],
14-
"patch": [ { "op": "replace", "path": "/0" } ],
15-
"error": "missing 'value' parameter" },
16-
17-
{ "comment": "missing 'value' parameter to test",
18-
"doc": [ null ],
19-
"patch": [ { "op": "test", "path": "/0" } ],
20-
"error": "missing 'value' parameter" },
21-
22-
{ "comment": "missing value parameter to test - where undef is falsy",
23-
"doc": [ false ],
24-
"patch": [ { "op": "test", "path": "/0" } ],
25-
"error": "missing 'value' parameter" },
26-
27-
{ "comment": "missing from parameter to copy",
28-
"doc": [ 1 ],
29-
"patch": [ { "op": "copy", "path": "/-" } ],
30-
"error": "missing 'from' parameter" },
31-
32-
{ "comment": "missing from parameter to move",
33-
"doc": { "foo": 1 },
34-
"patch": [ { "op": "move", "path": "" } ],
35-
"error": "missing 'from' parameter" },
36-
37-
{ "comment": "duplicate ops",
38-
"doc": { "foo": "bar" },
39-
"patch": [ { "op": "add", "path": "/baz", "value": "qux",
40-
"op": "move", "from":"/foo" } ],
41-
"error": "patch has two 'op' members",
42-
"disabled": true },
43-
447
{ "comment": "Adding to \"/-\" adds to the end of the array",
458
"doc": [ 1, 2 ],
469
"patch": [ { "op": "add", "path": "/-", "value": 3 } ],
@@ -86,11 +49,6 @@
8649
"patch": [{"op": "remove", "path": ""}],
8750
"error": "Can't remove whole document" },
8851

89-
{ "comment": "unrecognized op should fail",
90-
"doc": {"foo": 1},
91-
"patch": [{"op": "spam", "path": "/foo", "value": 1}],
92-
"error": "Unrecognized op 'spam'" },
93-
9452
{ "comment": "Ok to have doc as toplevel string?",
9553
"doc": 1,
9654
"patch": [{"op": "replace", "path": "", "value": "bar"}],
@@ -156,60 +114,6 @@
156114
"patch": [{"op": "test", "path":"", "value": ""}],
157115
"error": "test target value different - expected \"\", found false" },
158116

159-
{ "comment": "numeric literal with underscore",
160-
"doc": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
161-
"patch": [{"op":"test", "path": "/1_1", "value":11}],
162-
"error": "path '/1_1' not found" },
163-
164-
{ "comment": "numeric literal with hex",
165-
"doc": [0, 1],
166-
"patch": [{"op":"test", "path": "/0x1", "value":1}],
167-
"error": "path '/0x1' not found" },
168-
169-
{ "comment": "numeric literal, long integer",
170-
"doc": [0, 1],
171-
"patch": [{"op":"test", "path": "/1L", "value":1}],
172-
"error": "path '/1L' not found" },
173-
174-
{ "comment": "bad number (in intermediate path location)",
175-
"doc": [[0,[1]]],
176-
"patch": [{"op": "test", "path": "/0/1e0/0", "value": 1}],
177-
"error": "path '/0/1e0/0' not found" },
178-
179-
{ "comment": "bad number (in intermediate path location)",
180-
"doc": [[0,[1]]],
181-
"patch": [{"op": "test", "path": "/0/01/0", "value": 1}],
182-
"error": "path '/0/01/0' not found" },
183-
184-
{ "comment": "Don't convert number representation for object lookup",
185-
"doc": { "1e0": 1 },
186-
"patch": [{"op": "test", "path": "/1", "value": 1}],
187-
"error": "path '/1' not found" },
188-
189-
{ "comment": "Don't convert number representation for object lookup",
190-
"doc": { "1e0": 1 },
191-
"patch": [{"op": "test", "path": "/1e0", "value": 1}] },
192-
193-
{ "comment": "test remove with bad number should fail",
194-
"doc": {"foo": 1, "baz": [{"qux": "hello"}]},
195-
"patch": [{"op": "remove", "path": "/baz/1e0/qux"}],
196-
"error": "Path '/baz/1e0/qux' not found" },
197-
198-
{ "comment": "test replace with bad number should fail",
199-
"doc": [1, 2],
200-
"patch": [{"op": "replace", "path": "/1e0", "value": false}],
201-
"error": "non-array key '1e0' used on array" },
202-
203-
{ "comment": "test copy with bad number should fail",
204-
"doc": {"baz": [1,2,3], "bar": 1},
205-
"patch": [{"op": "copy", "from": "/baz/1e0", "path": "/boo"}],
206-
"error": "path '/baz/1e0' not found" },
207-
208-
{ "comment": "test move with bad number should fail",
209-
"doc": {"foo": 1, "baz": [1,2,3,4]},
210-
"patch": [{"op": "move", "from": "/baz/1e0", "path": "/foo"}],
211-
"error": "path '/baz/1e0' not found" },
212-
213117
{ "comment": "null within string",
214118
"doc": [ "foo\u0000foo" ],
215119
"patch": [{"op":"test", "path":"/0", "value":"foo\u0000foo"}] },
@@ -292,5 +196,22 @@
292196
"patch": {"op":"add", "path":"/1b", "value":"b"},
293197
"expected": {"0a":"a", "1b":"b", "2c": "c"} },
294198

199+
{ "comment": "Numerically equal must test equal",
200+
"doc": [1.00],
201+
"patch": [{"op": "test", "path":"/0", "value":1}]},
202+
203+
{ "comment": "Numerically equal must test equal",
204+
"doc": [1],
205+
"patch": [{"op": "test", "path":"/0", "value":1.00}]},
206+
207+
{ "comment": "Numerically equal must test equal",
208+
"doc": [1e0],
209+
"patch": [{"op": "test", "path":"/0", "value":1.00}]},
210+
211+
{ "comment": "append",
212+
"doc": [1, 2, 3, 4],
213+
"patch": [{"op": "append", "path": "/-", "value":[5, 6, 7, 8]}],
214+
"expected": [1, 2, 3, 4, 5, 6, 7, 8] },
215+
295216
{ "comment": "last" }
296217
]

0 commit comments

Comments
 (0)