@capture.dev/fast-json-patch 3.2.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.
- package/LICENSE.txt +23 -0
- package/README.md +428 -0
- package/dist/index.cjs +766 -0
- package/dist/index.d.cts +161 -0
- package/dist/index.d.ts +161 -0
- package/dist/index.js +726 -0
- package/package.json +71 -0
package/LICENSE.txt
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
(The MIT License)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2013, 2014, 2020 Joachim Wester (original maintainer)
|
|
4
|
+
Copyright (c) 2025 capture.dev (for modifications)
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
7
|
+
a copy of this software and associated documentation files (the
|
|
8
|
+
'Software'), to deal in the Software without restriction, including
|
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
12
|
+
the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be
|
|
15
|
+
included in all copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
20
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
21
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
22
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
23
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
JSON-Patch
|
|
2
|
+
===============
|
|
3
|
+
|
|
4
|
+
> A leaner and meaner implementation of JSON-Patch. Small footprint. High performance.
|
|
5
|
+
|
|
6
|
+
[](https://travis-ci.org/Starcounter-Jack/JSON-Patch)
|
|
7
|
+
|
|
8
|
+
With JSON-Patch, you can:
|
|
9
|
+
- **apply** patches (arrays) and single operations on JS object
|
|
10
|
+
- **validate** a sequence of patches
|
|
11
|
+
- **observe** for changes and **generate** patches when a change is detected
|
|
12
|
+
- **compare** two objects to obtain the difference
|
|
13
|
+
|
|
14
|
+
Tested in Firefox, Chrome, Edge, Safari, IE11, Deno and Node.js
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Why you should use JSON-Patch
|
|
18
|
+
|
|
19
|
+
JSON-Patch [(RFC6902)](http://tools.ietf.org/html/rfc6902) is a standard format that
|
|
20
|
+
allows you to update a JSON document by sending the changes rather than the whole document.
|
|
21
|
+
JSON Patch plays well with the HTTP PATCH verb (method) and REST style programming.
|
|
22
|
+
|
|
23
|
+
Mark Nottingham has a [nice blog]( http://www.mnot.net/blog/2012/09/05/patch) about it.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
[Download as ZIP](https://github.com/Starcounter-Jack/JSON-Patch/archive/master.zip) or install the current version using a package manager (and save it as a dependency):
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
# NPM
|
|
32
|
+
npm install fast-json-patch --save
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
## Adding to your project
|
|
37
|
+
|
|
38
|
+
### In a web browser
|
|
39
|
+
|
|
40
|
+
Load the bundled distribution script:
|
|
41
|
+
|
|
42
|
+
```html
|
|
43
|
+
<script src="dist/fast-json-patch.min.js"></script>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
In [browsers that support ECMAScript modules](https://caniuse.com/#feat=es6-module), the below code uses this library as a module:
|
|
47
|
+
|
|
48
|
+
```html
|
|
49
|
+
<script type="module">
|
|
50
|
+
import * as jsonpatch from 'fast-json-patch/index.mjs';
|
|
51
|
+
import { applyOperation } from 'fast-json-patch/index.mjs';
|
|
52
|
+
</script>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### In Node.js
|
|
56
|
+
|
|
57
|
+
In Node 12+ with `--experimental-modules` flag, the below code uses this library as an ECMAScript module:
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
import * as jsonpatch from 'fast-json-patch/index.mjs';
|
|
61
|
+
import { applyOperation } from 'fast-json-patch/index.mjs';
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
In Webpack (and most surely other bundlers based on Babel), the below code uses this library as an ECMAScript module:
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
import * as jsonpatch from 'fast-json-patch';
|
|
68
|
+
import { applyOperation } from 'fast-json-patch';
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
In standard Node, the below code uses this library as a CommonJS module:
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
const { applyOperation } = require('fast-json-patch');
|
|
75
|
+
const applyOperation = require('fast-json-patch').applyOperation;
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Directories
|
|
79
|
+
|
|
80
|
+
Directories used in this package:
|
|
81
|
+
|
|
82
|
+
- `dist/` - contains ES5 files for a Web browser
|
|
83
|
+
- `commonjs/` - contains CommonJS module and typings
|
|
84
|
+
- `module/` - contains ECMAScript module and typings
|
|
85
|
+
- `src/` - contains TypeScript source files
|
|
86
|
+
|
|
87
|
+
## API
|
|
88
|
+
|
|
89
|
+
#### `function applyPatch<T>(document: T, patch: Operation[], validateOperation?: boolean | Validator<T>, mutateDocument: boolean = true, banPrototypeModifications: boolean = true): PatchResult<T>`
|
|
90
|
+
|
|
91
|
+
Applies `patch` array on `obj`.
|
|
92
|
+
|
|
93
|
+
- `document` The document to patch
|
|
94
|
+
- `patch` a JSON-Patch array of operations to apply
|
|
95
|
+
- `validateOperation` Boolean for whether to validate each operation with our default validator, or to pass a validator callback
|
|
96
|
+
- `mutateDocument` Whether to mutate the original document or clone it before applying
|
|
97
|
+
- `banPrototypeModifications` Whether to ban modifications to `__proto__`, defaults to `true`.
|
|
98
|
+
|
|
99
|
+
An invalid patch results in throwing an error (see `jsonpatch.validate` for more information about the error object).
|
|
100
|
+
|
|
101
|
+
It modifies the `document` object and `patch` - it gets the values by reference.
|
|
102
|
+
If you would like to avoid touching your `patch` array values, clone them: `jsonpatch.applyPatch(document, jsonpatch.deepClone(patch))`.
|
|
103
|
+
|
|
104
|
+
Returns an array of [`OperationResult`](#operationresult-type) objects - one item for each item in `patches`, each item is an object `{newDocument: any, test?: boolean, removed?: any}`.
|
|
105
|
+
|
|
106
|
+
* `test` - boolean result of the test
|
|
107
|
+
* `remove`, `replace` and `move` - original object that has been removed
|
|
108
|
+
* `add` (only when adding to an array) - index at which item has been inserted (useful when using `-` alias)
|
|
109
|
+
|
|
110
|
+
- ** Note: It throws `TEST_OPERATION_FAILED` error if `test` operation fails. **
|
|
111
|
+
- ** Note II: the returned array has `newDocument` property that you can use as the final state of the patched document **.
|
|
112
|
+
- ** Note III: By default, when `banPrototypeModifications` is `true`, this method throws a `TypeError` when you attempt to modify an object's prototype.
|
|
113
|
+
|
|
114
|
+
- See [Validation notes](#validation-notes).
|
|
115
|
+
|
|
116
|
+
Example:
|
|
117
|
+
|
|
118
|
+
```js
|
|
119
|
+
var document = { firstName: "Albert", contactDetails: { phoneNumbers: [] } };
|
|
120
|
+
var patch = [
|
|
121
|
+
{ op: "replace", path: "/firstName", value: "Joachim" },
|
|
122
|
+
{ op: "add", path: "/lastName", value: "Wester" },
|
|
123
|
+
{ op: "add", path: "/contactDetails/phoneNumbers/0", value: { number: "555-123" } }
|
|
124
|
+
];
|
|
125
|
+
document = jsonpatch.applyPatch(document, patch).newDocument;
|
|
126
|
+
// document == { firstName: "Joachim", lastName: "Wester", contactDetails: { phoneNumbers: [{number:"555-123"}] } };
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### `function applyOperation<T>(document: T, operation: Operation, validateOperation: boolean | Validator<T> = false, mutateDocument: boolean = true, banPrototypeModifications: boolean = true, index: number = 0): OperationResult<T>`
|
|
130
|
+
|
|
131
|
+
Applies single operation object `operation` on `document`.
|
|
132
|
+
|
|
133
|
+
- `document` The document to patch
|
|
134
|
+
- `operation` The operation to apply
|
|
135
|
+
- `validateOperation` Whether to validate the operation, or to pass a validator callback
|
|
136
|
+
- `mutateDocument` Whether to mutate the original document or clone it before applying
|
|
137
|
+
- `banPrototypeModifications` Whether to ban modifications to `__proto__`, defaults to `true`.
|
|
138
|
+
- `index` The index of the operation in your patch array. Useful for better error reporting when that operation fails to apply.
|
|
139
|
+
|
|
140
|
+
It modifies the `document` object and `operation` - it gets the values by reference.
|
|
141
|
+
If you would like to avoid touching your values, clone them: `jsonpatch.applyOperation(document, jsonpatch.deepClone(operation))`.
|
|
142
|
+
|
|
143
|
+
Returns an [`OperationResult`](#operationresult-type) object `{newDocument: any, test?: boolean, removed?: any}`.
|
|
144
|
+
|
|
145
|
+
- ** Note: It throws `TEST_OPERATION_FAILED` error if `test` operation fails. **
|
|
146
|
+
- ** Note II: By default, when `banPrototypeModifications` is `true`, this method throws a `TypeError` when you attempt to modify an object's prototype.
|
|
147
|
+
|
|
148
|
+
- See [Validation notes](#validation-notes).
|
|
149
|
+
|
|
150
|
+
Example:
|
|
151
|
+
|
|
152
|
+
```js
|
|
153
|
+
var document = { firstName: "Albert", contactDetails: { phoneNumbers: [] } };
|
|
154
|
+
var operation = { op: "replace", path: "/firstName", value: "Joachim" };
|
|
155
|
+
document = jsonpatch.applyOperation(document, operation).newDocument;
|
|
156
|
+
// document == { firstName: "Joachim", contactDetails: { phoneNumbers: [] }}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### `jsonpatch.applyReducer<T>(document: T, operation: Operation, index: number): T`
|
|
160
|
+
|
|
161
|
+
**Ideal for `patch.reduce(jsonpatch.applyReducer, document)`**.
|
|
162
|
+
|
|
163
|
+
Applies single operation object `operation` on `document`.
|
|
164
|
+
|
|
165
|
+
Returns the a modified document.
|
|
166
|
+
|
|
167
|
+
Note: It throws `TEST_OPERATION_FAILED` error if `test` operation fails.
|
|
168
|
+
|
|
169
|
+
Example:
|
|
170
|
+
|
|
171
|
+
```js
|
|
172
|
+
var document = { firstName: "Albert", contactDetails: { phoneNumbers: [ ] } };
|
|
173
|
+
var patch = [
|
|
174
|
+
{ op:"replace", path: "/firstName", value: "Joachim" },
|
|
175
|
+
{ op:"add", path: "/lastName", value: "Wester" },
|
|
176
|
+
{ op:"add", path: "/contactDetails/phoneNumbers/0", value: { number: "555-123" } }
|
|
177
|
+
];
|
|
178
|
+
var updatedDocument = patch.reduce(applyReducer, document);
|
|
179
|
+
// updatedDocument == { firstName:"Joachim", lastName:"Wester", contactDetails:{ phoneNumbers[ {number:"555-123"} ] } };
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
#### `jsonpatch.deepClone(value: any): any`
|
|
183
|
+
|
|
184
|
+
Returns deeply cloned value.
|
|
185
|
+
|
|
186
|
+
#### `jsonpatch.escapePathComponent(path: string): string`
|
|
187
|
+
|
|
188
|
+
Returns the escaped path.
|
|
189
|
+
|
|
190
|
+
#### `jsonpatch.unescapePathComponent(path: string): string`
|
|
191
|
+
|
|
192
|
+
Returns the unescaped path.
|
|
193
|
+
|
|
194
|
+
#### `jsonpatch.getValueByPointer(document: object, pointer: string)`
|
|
195
|
+
|
|
196
|
+
Retrieves a value from a JSON document by a JSON pointer.
|
|
197
|
+
|
|
198
|
+
Returns the value.
|
|
199
|
+
|
|
200
|
+
#### `jsonpatch.observe(document: any, callback?: Function): Observer`
|
|
201
|
+
|
|
202
|
+
Sets up an deep observer on `document` that listens for changes in object tree. When changes are detected, the optional
|
|
203
|
+
callback is called with the generated patches array as the parameter.
|
|
204
|
+
|
|
205
|
+
Returns `observer`.
|
|
206
|
+
|
|
207
|
+
#### `jsonpatch.generate(document: any, observer: Observer, invertible = false): Operation[]`
|
|
208
|
+
|
|
209
|
+
If there are pending changes in `obj`, returns them synchronously. If a `callback` was defined in `observe`
|
|
210
|
+
method, it will be triggered synchronously as well. If `invertible` is true, then each change will be preceded by a test operation of the value before the change.
|
|
211
|
+
|
|
212
|
+
If there are no pending changes in `obj`, returns an empty array (length 0).
|
|
213
|
+
|
|
214
|
+
Example:
|
|
215
|
+
|
|
216
|
+
```js
|
|
217
|
+
var document = { firstName: "Joachim", lastName: "Wester", contactDetails: { phoneNumbers: [ { number:"555-123" }] } };
|
|
218
|
+
var observer = jsonpatch.observe(document);
|
|
219
|
+
document.firstName = "Albert";
|
|
220
|
+
document.contactDetails.phoneNumbers[0].number = "123";
|
|
221
|
+
document.contactDetails.phoneNumbers.push({ number:"456" });
|
|
222
|
+
var patch = jsonpatch.generate(observer);
|
|
223
|
+
// patch == [
|
|
224
|
+
// { op: "replace", path: "/firstName", value: "Albert"},
|
|
225
|
+
// { op: "replace", path: "/contactDetails/phoneNumbers/0/number", value: "123" },
|
|
226
|
+
// { op: "add", path: "/contactDetails/phoneNumbers/1", value: {number:"456"}}
|
|
227
|
+
// ];
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Example of generating patches with test operations for values in the first object:
|
|
231
|
+
|
|
232
|
+
```js
|
|
233
|
+
var document = { firstName: "Joachim", lastName: "Wester", contactDetails: { phoneNumbers: [ { number:"555-123" }] } };
|
|
234
|
+
var observer = jsonpatch.observe(document);
|
|
235
|
+
document.firstName = "Albert";
|
|
236
|
+
document.contactDetails.phoneNumbers[0].number = "123";
|
|
237
|
+
document.contactDetails.phoneNumbers.push({ number:"456" });
|
|
238
|
+
var patch = jsonpatch.generate(observer, true);
|
|
239
|
+
// patch == [
|
|
240
|
+
// { op: "test", path: "/firstName", value: "Joachim"},
|
|
241
|
+
// { op: "replace", path: "/firstName", value: "Albert"},
|
|
242
|
+
// { op: "test", path: "/contactDetails/phoneNumbers/0/number", value: "555-123" },
|
|
243
|
+
// { op: "replace", path: "/contactDetails/phoneNumbers/0/number", value: "123" },
|
|
244
|
+
// { op: "add", path: "/contactDetails/phoneNumbers/1", value: {number:"456"}}
|
|
245
|
+
// ];
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### `jsonpatch.unobserve(document, observer)`
|
|
249
|
+
```typescript
|
|
250
|
+
jsonpatch.unobserve(document: any, observer: Observer): void
|
|
251
|
+
|
|
252
|
+
type JsonableObj = { [key:string]: Jsonable };
|
|
253
|
+
type JsonableArr = Jsonable[];
|
|
254
|
+
type Jsonable = JsonableArr | JsonableObj | string | number | boolean | null;
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Destroys the observer set up on `document`.
|
|
258
|
+
|
|
259
|
+
Any remaining changes are delivered synchronously (as in `jsonpatch.generate`). Note: this is different that ES6/7 `Object.unobserve`, which delivers remaining changes asynchronously.
|
|
260
|
+
|
|
261
|
+
#### `jsonpatch.compare(document1, document2, invertible)`
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
jsonpatch.compare(document1: Jsonable, document2: Jsonable, invertible = false): Operation[]
|
|
265
|
+
|
|
266
|
+
type JsonableObj = { [key:string]: Jsonable };
|
|
267
|
+
type JsonableArr = Jsonable[];
|
|
268
|
+
type Jsonable = JsonableArr | JsonableObj | string | number | boolean | null;
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Compares object trees `document1` and `document2` and returns the difference relative to `document1` as a patches array. If `invertible` is true, then each change will be preceded by a test operation of the value in `document1`.
|
|
272
|
+
|
|
273
|
+
If there are no differences, returns an empty array (length 0).
|
|
274
|
+
|
|
275
|
+
Example:
|
|
276
|
+
|
|
277
|
+
```js
|
|
278
|
+
var documentA = {user: {firstName: "Albert", lastName: "Einstein"}};
|
|
279
|
+
var documentB = {user: {firstName: "Albert", lastName: "Collins"}};
|
|
280
|
+
var diff = jsonpatch.compare(documentA, documentB);
|
|
281
|
+
//diff == [{op: "replace", path: "/user/lastName", value: "Collins"}]
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Example of comparing two object trees with test operations for values in the first object:
|
|
285
|
+
|
|
286
|
+
```js
|
|
287
|
+
var documentA = {user: {firstName: "Albert", lastName: "Einstein"}};
|
|
288
|
+
var documentB = {user: {firstName: "Albert", lastName: "Collins"}};
|
|
289
|
+
var diff = jsonpatch.compare(documentA, documentB, true);
|
|
290
|
+
//diff == [
|
|
291
|
+
// {op: "test", path: "/user/lastName", value: "Einstein"},
|
|
292
|
+
// {op: "replace", path: "/user/lastName", value: "Collins"}
|
|
293
|
+
// ];
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
#### `jsonpatch.validate(patch: Operation[], document?: any, validator?: Function): JsonPatchError`
|
|
297
|
+
|
|
298
|
+
See [Validation notes](#validation-notes)
|
|
299
|
+
|
|
300
|
+
Validates a sequence of operations. If `document` parameter is provided, the sequence is additionally validated against the object tree.
|
|
301
|
+
|
|
302
|
+
If there are no errors, returns undefined. If there is an errors, returns a JsonPatchError object with the following properties:
|
|
303
|
+
|
|
304
|
+
- `name` String - short error code
|
|
305
|
+
- `message` String - long human readable error message
|
|
306
|
+
- `index` Number - index of the operation in the sequence
|
|
307
|
+
- `operation` Object - reference to the operation
|
|
308
|
+
- `tree` Object - reference to the tree
|
|
309
|
+
|
|
310
|
+
Possible errors:
|
|
311
|
+
|
|
312
|
+
Error name | Error message
|
|
313
|
+
------------------------------|------------
|
|
314
|
+
SEQUENCE_NOT_AN_ARRAY | Patch sequence must be an array
|
|
315
|
+
OPERATION_NOT_AN_OBJECT | Operation is not an object
|
|
316
|
+
OPERATION_OP_INVALID | Operation `op` property is not one of operations defined in RFC-6902
|
|
317
|
+
OPERATION_PATH_INVALID | Operation `path` property is not a valid string
|
|
318
|
+
OPERATION_FROM_REQUIRED | Operation `from` property is not present (applicable in `move` and `copy` operations)
|
|
319
|
+
OPERATION_VALUE_REQUIRED | Operation `value` property is not present, or `undefined` (applicable in `add`, `replace` and `test` operations)
|
|
320
|
+
OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED | Operation `value` property object has at least one `undefined` value (applicable in `add`, `replace` and `test` operations)
|
|
321
|
+
OPERATION_PATH_CANNOT_ADD | Cannot perform an `add` operation at the desired path
|
|
322
|
+
OPERATION_PATH_UNRESOLVABLE | Cannot perform the operation at a path that does not exist
|
|
323
|
+
OPERATION_FROM_UNRESOLVABLE | Cannot perform the operation from a path that does not exist
|
|
324
|
+
OPERATION_PATH_ILLEGAL_ARRAY_INDEX | Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index
|
|
325
|
+
OPERATION_VALUE_OUT_OF_BOUNDS | The specified index MUST NOT be greater than the number of elements in the array
|
|
326
|
+
TEST_OPERATION_FAILED | When operation is `test` and the test fails, applies to `applyReducer`.
|
|
327
|
+
|
|
328
|
+
Example:
|
|
329
|
+
|
|
330
|
+
```js
|
|
331
|
+
var obj = {user: {firstName: "Albert"}};
|
|
332
|
+
var patches = [{op: "replace", path: "/user/firstName", value: "Albert"}, {op: "replace", path: "/user/lastName", value: "Einstein"}];
|
|
333
|
+
var errors = jsonpatch.validate(patches, obj);
|
|
334
|
+
if (errors.length == 0) {
|
|
335
|
+
//there are no errors!
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
for (var i=0; i < errors.length; i++) {
|
|
339
|
+
if (!errors[i]) {
|
|
340
|
+
console.log("Valid patch at index", i, patches[i]);
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
console.error("Invalid patch at index", i, errors[i], patches[i]);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## `OperationResult` Type
|
|
350
|
+
|
|
351
|
+
Functions `applyPatch` and `applyOperation` both return `OperationResult` object. This object is:
|
|
352
|
+
|
|
353
|
+
```ts
|
|
354
|
+
{newDocument: any, test?: boolean, removed?: any}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Where:
|
|
358
|
+
|
|
359
|
+
- `newDocument`: the new state of the document after the patch/operation is applied.
|
|
360
|
+
- `test`: if the operation was a `test` operation. This will be its result.
|
|
361
|
+
- `removed`: contains the removed, moved, or replaced values from the document after a `remove`, `move` or `replace` operation.
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
## Validation Notes
|
|
365
|
+
|
|
366
|
+
Functions `applyPatch`, `applyOperation`, and `validate` accept a `validate`/ `validator` parameter:
|
|
367
|
+
|
|
368
|
+
- If the `validateOperation` parameter is set to `false`, validation will not occur.
|
|
369
|
+
- If set to `true`, the patch is extensively validated before applying using jsonpatch's default validation.
|
|
370
|
+
- If set to a `function` callback, the patch is validated using that function.
|
|
371
|
+
|
|
372
|
+
If you pass a validator, it will be called with four parameters for each operation, `function(operation, index, tree, existingPath)` and it is expected to throw `JsonPatchError` when your conditions are not met.
|
|
373
|
+
|
|
374
|
+
- `operation` The operation it self.
|
|
375
|
+
- `index` `operation`'s index in the patch array (if application).
|
|
376
|
+
- `tree` The object that is supposed to be patched.
|
|
377
|
+
- `existingPath` the path `operation` points to.
|
|
378
|
+
|
|
379
|
+
## Overwriting and `move` Operation
|
|
380
|
+
|
|
381
|
+
When the target of the move operation already exists, it is cached, deep cloned and returned as `removed` in `OperationResult`.
|
|
382
|
+
|
|
383
|
+
## `undefined`s (JS to JSON projection)
|
|
384
|
+
|
|
385
|
+
As `undefined` type does not exist in JSON, it's also not a valid value of JSON Patch operation. Therefore `jsonpatch` will not generate JSON Patches that sets anything to `undefined`.
|
|
386
|
+
|
|
387
|
+
Whenever a value is set to `undefined` in JS, JSON-Patch methods `generate` and `compare` will treat it similarly to how JavaScript method [`JSON.stringify` (MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) treats them:
|
|
388
|
+
|
|
389
|
+
> If `undefined` (...) is encountered during conversion it is either omitted (when it is found in an object) or censored to `null` (when it is found in an array).
|
|
390
|
+
|
|
391
|
+
See the [ECMAScript spec](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-json.stringify) for details.
|
|
392
|
+
|
|
393
|
+
## Specs/tests
|
|
394
|
+
|
|
395
|
+
- [Run in browser](http://starcounter-jack.github.io/JSON-Patch/test/)
|
|
396
|
+
|
|
397
|
+
## [Contributing](CONTRIBUTING.md)
|
|
398
|
+
|
|
399
|
+
## Changelog
|
|
400
|
+
|
|
401
|
+
To see the list of recent changes, see [Releases](https://github.com/Starcounter-Jack/JSON-Patch/releases).
|
|
402
|
+
|
|
403
|
+
## Footprint
|
|
404
|
+
4 KB minified and gzipped (12 KB minified)
|
|
405
|
+
|
|
406
|
+
## Performance
|
|
407
|
+
|
|
408
|
+
##### [`add` benchmark](https://run.perf.zone/view/JSON-Patch-Add-Operation-1535541298893)
|
|
409
|
+
|
|
410
|
+

|
|
411
|
+
|
|
412
|
+
##### [`replace` benchmark](https://run.perf.zone/view/JSON-Patch-Replace-Operation-1535540952263)
|
|
413
|
+
|
|
414
|
+

|
|
415
|
+
|
|
416
|
+
Tested on 29.08.2018. Compared libraries:
|
|
417
|
+
|
|
418
|
+
- [Starcounter-Jack/JSON-Patch](https://www.npmjs.com/package/fast-json-patch) 2.0.6
|
|
419
|
+
- [bruth/jsonpatch-js](https://www.npmjs.com/package/json-patch) 0.7.0
|
|
420
|
+
- [dharmafly/jsonpatch.js](https://www.npmjs.com/package/jsonpatch) 3.0.1
|
|
421
|
+
- [jiff](https://www.npmjs.com/package/jiff) 0.7.3
|
|
422
|
+
- [RFC6902](https://www.npmjs.com/package/rfc6902) 2.4.0
|
|
423
|
+
|
|
424
|
+
We aim the tests to be fair. Our library puts performance as the #1 priority, while other libraries can have different priorities. If you'd like to update the benchmarks or add a library, please fork the [perf.zone](https://perf.zone) benchmarks linked above and open an issue to include new results.
|
|
425
|
+
|
|
426
|
+
## License
|
|
427
|
+
|
|
428
|
+
MIT
|