Skip to content

Commit be72bd3

Browse files
authored
Merge pull request #961 from streamich/improve-json-patch-diff
Improve JSON Patch diff
2 parents 13ff15f + 662b7e3 commit be72bd3

File tree

8 files changed

+1186
-5
lines changed

8 files changed

+1186
-5
lines changed

packages/json-joy/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,3 @@ export type * from './json-crdt';
1212
export type * from './json-crdt-patch';
1313
export type * from './json-crdt-extensions';
1414
export type * from './json-patch/types';
15-
export type * from '../../json-path/src/types';

packages/json-joy/src/json-patch-diff/JsonPatchDiff.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {deepEqual} from '@jsonjoy.com/util/lib/json-equal/deepEqual';
22
import * as str from '../util/diff/str';
33
import * as line from '../util/diff/line';
44
import {structHash} from '../json-hash';
5+
import {escapeComponent} from '@jsonjoy.com/json-pointer/lib/util';
56
import type {Operation} from '../json-patch/codec/json/types';
67

78
export class JsonPatchDiff {
@@ -34,14 +35,14 @@ export class JsonPatchDiff {
3435
const val1 = src[key];
3536
const val2 = dst[key];
3637
if (val1 === val2) continue;
37-
this.diffAny(path + '/' + key, val1, val2);
38+
this.diffAny(path + '/' + escapeComponent(key), val1, val2);
3839
} else {
39-
patch.push({op: 'remove', path: path + '/' + key});
40+
patch.push({op: 'remove', path: path + '/' + escapeComponent(key)});
4041
}
4142
}
4243
for (const key in dst) {
4344
if (key in src) continue;
44-
patch.push({op: 'add', path: path + '/' + key, value: dst[key]});
45+
patch.push({op: 'add', path: path + '/' + escapeComponent(key), value: dst[key]});
4546
}
4647
}
4748

@@ -78,6 +79,16 @@ export class JsonPatchDiff {
7879
}
7980

8081
public diffAny(path: string, src: unknown, dst: unknown): void {
82+
// Check for type changes first
83+
const srcType = Array.isArray(src) ? 'array' : typeof src;
84+
const dstType = Array.isArray(dst) ? 'array' : typeof dst;
85+
86+
if (srcType !== dstType) {
87+
// Different types, replace entirely
88+
this.diffVal(path, src, dst);
89+
return;
90+
}
91+
8192
switch (typeof src) {
8293
case 'string': {
8394
if (typeof dst === 'string') this.diffStr(path, src, dst);

0 commit comments

Comments
 (0)