Skip to content

Commit bd90f08

Browse files
committed
added support for replace
1 parent caaee21 commit bd90f08

File tree

1 file changed

+29
-20
lines changed

1 file changed

+29
-20
lines changed

jsondiff.js

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ export default class JSONDiff {
66
constructor(oldObj, newObj) {
77
this.oldObj = oldObj;
88
this.newObj = newObj;
9-
this.jsonPatch = [];
9+
this.jsonPatch = [];
10+
this.deletes = {};
1011
}
1112

1213
isEmpty = (obj) => {
@@ -33,12 +34,16 @@ export default class JSONDiff {
3334
generateArrDiff(oldArr, newArr, path) {
3435
this.walkMiddleSnake(oldArr, newArr, path);
3536
}
36-
37-
generateObjDiff(oldObj=this.oldObj, newObj=this.newObj, path='') {
37+
setDelete(path) {
38+
// make sure inserted to jsonPatch first else will be error
39+
this.deletes[path] = this.jsonPatch.length - 1;
40+
}
41+
generateObjDiff(oldObj=this.oldObj, newObj=this.newObj, path='', pushToArr=this.jsonPatch) {
3842
if (this.isEmpty(oldObj)) {
39-
this.jsonPatch.push({op: "add", path: "/", value: newObj});
43+
pushToArr.push({op: "add", path: "/", value: newObj});
4044
} else if (this.isEmpty(newObj)) {
41-
this.jsonPatch.push({op: "delete", path: "/"});
45+
pushToArr.push({op: "delete", path: "/"});
46+
this.setDelete('/');
4247
} else {
4348
const oldKeys = this.getKeys(oldObj);
4449
const newKeys = this.getKeys(newObj);
@@ -51,10 +56,12 @@ export default class JSONDiff {
5156
// 1.4. else same, then skip
5257

5358
if (!newObj.hasOwnProperty(oldKeys[t])) {
54-
this.jsonPatch.push({op: "delete", path: `${path}/${oldKeys[t]}`});
59+
const _p = `${path}/${oldKeys[t]}`;
60+
pushToArr.push({op: "delete", path: _p});
61+
this.setDelete(_p);
5562
}
5663
else if (newObj[oldKeys[t]] != oldObj[oldKeys[t]]) {
57-
this.jsonPatch.push({op: "replace", path: `${path}/${oldKeys[t]}`, value: newObj[oldKeys[t]]});
64+
pushToArr.push({op: "replace", path: `${path}/${oldKeys[t]}`, value: newObj[oldKeys[t]]});
5865
}
5966
}
6067

@@ -64,7 +71,10 @@ export default class JSONDiff {
6471
// 2.3 else recursive call
6572

6673
if (!newObj.hasOwnProperty(oldKeys[t])) {
67-
this.jsonPatch.push({op: "delete", path: `${path}/${oldKeys[t]}`});
74+
const _p = `${path}/${oldKeys[t]}`;
75+
pushToArr.push({op: "delete", path: _p});
76+
this.setDelete(_p);
77+
6878
} else {
6979
this.generateObjDiff(oldObj[oldKeys[t]], newObj[oldKeys[t]], `${path}/${oldKeys[t]}`);
7080
}
@@ -78,7 +88,7 @@ export default class JSONDiff {
7888
// 4. add all the remaining new properties to patch
7989
for (let t = 0; t < newKeys.length; t++) {
8090
if (!this.isEmpty(newObj[newKeys[t]]) && !oldObj.hasOwnProperty(newKeys[t])) {
81-
this.jsonPatch.push({op: "add", path: `${path}/${newKeys[t]}`, value: newObj[newKeys[t]]});
91+
pushToArr.push({op: "add", path: `${path}/${newKeys[t]}`, value: newObj[newKeys[t]]});
8292
}
8393
}
8494
}
@@ -206,19 +216,16 @@ export default class JSONDiff {
206216
];
207217
}
208218
callbackFunc (x1, y1, x2, y2, oldArr, newArr, path_) {
209-
const lastIndex = Math.max(0, this.jsonPatch.length - 1);
210219
if (x1 == x2) {
211-
if (typeof newArr[y1] == 'object' && !Array.isArray(newArr[y1]) &&
212-
(this.jsonPatch[lastIndex]?.path == `${path_}/${y1}`
213-
&& this.jsonPatch[lastIndex]?.op == 'delete')) {
220+
const _p = `${path_}/${y1}`;
221+
if (typeof newArr[y1] == 'object' && !Array.isArray(newArr[y1]) && this.deletes.hasOwnProperty(_p)) {
214222
// if there is a delete at same index and the type is object check for partial update
215-
this.jsonPatch.pop();
216-
this.generateObjDiff(oldArr[y1], newArr[y1], `${path_}/${y1}`);
223+
const arr = [];
224+
this.generateObjDiff(oldArr[y1], newArr[y1], `${path_}/${y1}`, arr);
225+
this.jsonPatch.splice(this.deletes[_p], 1, ...arr);
217226
} else {
218-
if ((this.jsonPatch[lastIndex]?.path == `${path_}/${y1}`
219-
&& this.jsonPatch[lastIndex]?.op == 'delete')) {
220-
this.jsonPatch.pop();
221-
this.jsonPatch.push({
227+
if (this.deletes.hasOwnProperty(_p)) {
228+
this.jsonPatch.splice(this.deletes[_p], 1, {
222229
op: 'replace',
223230
path: `${path_}/${y1}`,
224231
value: newArr[y1]
@@ -232,10 +239,12 @@ export default class JSONDiff {
232239
}
233240
}
234241
} else if(y1 == y2) {
242+
const _p = `${path_}/${x1}`;
235243
this.jsonPatch.push({
236244
op: 'delete',
237-
path: `${path_}/${x1}`
245+
path: _p
238246
});
247+
this.setDelete(_p);
239248
}
240249
}
241250
walkMiddleSnake(oldArr, newArr, path_) {

0 commit comments

Comments
 (0)