Skip to content

Commit 623fc53

Browse files
committed
fix: respect maxDepth for array values
1 parent dbf3739 commit 623fc53

File tree

2 files changed

+65
-4
lines changed

2 files changed

+65
-4
lines changed

src/index.spec.ts

+51-1
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ describe('a generate json patch function', () => {
662662
fourthLevel: 'hello-world',
663663
},
664664
thirdLevelTwo: 'hello',
665+
thirdLevelThree: ['hello', 'world'],
665666
},
666667
},
667668
};
@@ -673,6 +674,7 @@ describe('a generate json patch function', () => {
673674
fourthLevel: 'hello-brave-new-world',
674675
},
675676
thirdLevelTwo: 'hello',
677+
thirdLevelThree: ['hello', 'world'],
676678
},
677679
},
678680
};
@@ -688,13 +690,16 @@ describe('a generate json patch function', () => {
688690
fourthLevel: 'hello-brave-new-world',
689691
},
690692
thirdLevelTwo: 'hello',
693+
thirdLevelThree: ['hello', 'world'],
691694
},
692695
},
693696
]);
694697
});
695698

696699
it('detects changes as a given depth of 4', () => {
697-
const patch = generateJSONPatch(before, after, { maxDepth: 4 });
700+
const afterModified = structuredClone(after);
701+
afterModified.firstLevel.secondLevel.thirdLevelTwo = 'hello-world';
702+
const patch = generateJSONPatch(before, afterModified, { maxDepth: 4 });
698703
expect(patch).to.eql([
699704
{
700705
op: 'replace',
@@ -703,6 +708,51 @@ describe('a generate json patch function', () => {
703708
fourthLevel: 'hello-brave-new-world',
704709
},
705710
},
711+
{
712+
op: 'replace',
713+
path: '/firstLevel/secondLevel/thirdLevelTwo',
714+
value: 'hello-world',
715+
},
716+
]);
717+
});
718+
719+
it('detects changes as a given depth of 4 for an array value', () => {
720+
const afterModified = structuredClone(before);
721+
afterModified.firstLevel.secondLevel.thirdLevelThree = ['test'];
722+
const patch = generateJSONPatch(before, afterModified, { maxDepth: 4 });
723+
expect(patch).to.eql([
724+
{
725+
op: 'replace',
726+
path: '/firstLevel/secondLevel/thirdLevelThree',
727+
value: ['test'],
728+
},
729+
]);
730+
});
731+
732+
it('detects changes as a given depth of 4 for an removed array value', () => {
733+
const afterModified = structuredClone(before);
734+
// @ts-ignore
735+
delete afterModified.firstLevel.secondLevel.thirdLevelThree;
736+
const patch = generateJSONPatch(before, afterModified, { maxDepth: 4 });
737+
expect(patch).to.eql([
738+
{
739+
op: 'remove',
740+
path: '/firstLevel/secondLevel/thirdLevelThree',
741+
},
742+
]);
743+
});
744+
745+
it('detects changes as a given depth of 4 for an nullyfied array value', () => {
746+
const afterModified = structuredClone(before);
747+
// @ts-ignore
748+
afterModified.firstLevel.secondLevel.thirdLevelThree = null;
749+
const patch = generateJSONPatch(before, afterModified, { maxDepth: 4 });
750+
expect(patch).to.eql([
751+
{
752+
op: 'replace',
753+
path: '/firstLevel/secondLevel/thirdLevelThree',
754+
value: null,
755+
},
706756
]);
707757
});
708758
});

src/index.ts

+14-3
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ export function generateJSONPatch(
9191
const patch: Patch = [];
9292
const hasPropertyFilter = typeof propertyFilter === 'function';
9393

94+
function maxDepthReached(path: string) {
95+
return maxDepth <= path.split('/').length;
96+
}
97+
9498
function compareArrays(leftArr: any[], rightArr: any[], path: string) {
9599
// if arrays are equal, no further comparison is required
96100
if (JSON.stringify(leftArr) === JSON.stringify(rightArr)) return;
@@ -105,6 +109,11 @@ export function generateJSONPatch(
105109
let currentIndex = leftArr.length - 1;
106110
const targetHashes: string[] = [];
107111

112+
if (maxDepthReached(path)) {
113+
patch.push({ op: 'replace', path: path, value: rightArr });
114+
return;
115+
}
116+
108117
// Change iteration direction: from back to front
109118
for (let i = leftArr.length - 1; i >= 0; i--) {
110119
const newPathIndex = `${path}/${currentIndex--}`;
@@ -154,7 +163,7 @@ export function generateJSONPatch(
154163
path === '' && [leftJsonValue, rightJsonValue].every(Array.isArray);
155164

156165
if (isPrimitiveValue(leftJsonValue) || isPrimitiveValue(rightJsonValue)) {
157-
if (leftJsonValue !== rightJsonValue) {
166+
if (JSON.stringify(leftJsonValue) !== JSON.stringify(rightJsonValue)) {
158167
patch.push({ op: 'replace', path: path, value: rightJsonValue });
159168
}
160169
return;
@@ -186,8 +195,10 @@ export function generateJSONPatch(
186195
compareArrays(leftValue, rightValue, newPath);
187196
} else if (isJsonObject(rightValue)) {
188197
if (isJsonObject(leftValue)) {
189-
if (maxDepth <= newPath.split('/').length) {
190-
patch.push({ op: 'replace', path: newPath, value: rightValue });
198+
if (maxDepthReached(newPath)) {
199+
if (JSON.stringify(leftValue) !== JSON.stringify(rightValue)) {
200+
patch.push({ op: 'replace', path: newPath, value: rightValue });
201+
}
191202
} else {
192203
compareObjects(newPath, leftValue, rightValue);
193204
}

0 commit comments

Comments
 (0)