Skip to content

Commit

Permalink
fix(get-struct-paths): path with empty keys (#48)
Browse files Browse the repository at this point in the history
* fix: root path

* fix: nested empty string path

* test: adjust some tests

* refactor: change conditional order

* feat: update compiled scripts

* Update get-diff.spec.ts
  • Loading branch information
lukascivil authored Jul 25, 2023
1 parent cd0d1e1 commit ab9831e
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 38 deletions.
34 changes: 17 additions & 17 deletions dist.browser/json-difference.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const O = (f, n) => {
const g = (f, n) => {
const o = [];
for (const e in f)
if (n.hasOwnProperty(e)) {
Expand All @@ -11,7 +11,7 @@ const O = (f, n) => {
o.push([e, f[e], n[e]]);
}
return o;
}, g = (f, n) => {
}, d = (f, n) => {
const o = [];
let e = 0;
for (const i in f)
Expand All @@ -20,29 +20,29 @@ const O = (f, n) => {
o[e] = [i, y], e++;
}
return o;
}, p = (f, n, o, e) => {
}, r = (f, n, o, e) => {
const i = e ? f ? "[" : "." : "/", y = e ? f ? "]" : "" : f ? "[]" : "";
return n !== "" ? `${n}${i}${o}${y}` : `${e && f ? "[" : ""}${o}${y}`;
}, d = (f, n = !1, o, e = "") => {
o === void 0 && (o = Array.isArray(f) ? { "": "@[]" } : { "": "@{}" });
return n === "__start__" ? `${e && f ? "[" : ""}${o}${y}` : `${n}${i}${o}${y}`;
}, s = (f, n = !1, o, e = "__start__") => {
o === void 0 && (o = Array.isArray(f) ? { __root__: "@[]" } : { __root__: "@{}" });
for (const i of Object.keys(f)) {
const y = p(Array.isArray(f), e, i, n);
typeof f[i] == "object" && f[i] !== null ? (Object.keys(f[i]).length === 0 ? o[y] = f[i] : o[y] = Array.isArray(f[i]) ? "@[]" : "@{}", d(f[i], n, o, y)) : o[y] = f[i];
const y = r(Array.isArray(f), e, i, n);
typeof f[i] == "object" && f[i] !== null ? (Object.keys(f[i]).length === 0 ? o[y] = f[i] : o[y] = Array.isArray(f[i]) ? "@[]" : "@{}", s(f[i], n, o, y)) : o[y] = f[i];
}
return o;
}, $ = {
}, O = {
isLodashLike: !1
}, b = (f, n, o) => {
const { isLodashLike: e } = o ?? $, i = {
}, p = (f, n, o) => {
const { isLodashLike: e } = o ?? O, i = {
added: [],
removed: [],
edited: []
}, y = d(f, e), s = d(n, e);
return i.removed = g(y, s), i.added = g(s, y), i.edited = O(y, s), i;
}, y = s(f, e), _ = s(n, e);
return i.removed = d(y, _), i.added = d(_, y), i.edited = g(y, _), i;
};
export {
b as getDiff,
O as getEditedPaths,
g as getPathsDiff,
d as getStructPaths
p as getDiff,
g as getEditedPaths,
d as getPathsDiff,
s as getStructPaths
};
2 changes: 1 addition & 1 deletion dist.browser/json-difference.umd.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 41 additions & 2 deletions src/core/get-diff.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,47 @@ describe('GetDiff function', () => {
test('Should return the difference between [] and {}', () => {
const struct1 = [] as any
const struct2 = {}
const expectedResult: Delta = { edited: [['', [], {}]], added: [], removed: [] }
const expectedLodashResult: Delta = { edited: [['', [], {}]], added: [], removed: [] }
const expectedResult: Delta = { edited: [['__root__', [], {}]], added: [], removed: [] }
const expectedLodashResult: Delta = { edited: [['__root__', [], {}]], added: [], removed: [] }

const result = getDiff(struct1, struct2)
const lodashResult = getDiff(struct1, struct2, { isLodashLike: true })

expect(result).toEqual(expectedResult)
expect(lodashResult).toEqual(expectedLodashResult)
})

test('Should return the difference between [] and {} with nested elements', () => {
const struct1 = [{}] as any
const struct2 = { a: {} }
const expectedResult: Delta = { edited: [['__root__', [], {}]], added: [['a', {}]], removed: [['0[]', {}]] }
const expectedLodashResult: Delta = { edited: [['__root__', [], {}]], added: [['a', {}]], removed: [['[0]', {}]] }

const result = getDiff(struct1, struct2)
const lodashResult = getDiff(struct1, struct2, { isLodashLike: true })

expect(result).toEqual(expectedResult)
expect(lodashResult).toEqual(expectedLodashResult)
})

test('Should return the difference between [] and {} with empty key', () => {
const struct1 = [{}] as any
const struct2 = { '': {} }
const expectedResult: Delta = { edited: [['__root__', [], {}]], added: [['', {}]], removed: [['0[]', {}]] }
const expectedLodashResult: Delta = { edited: [['__root__', [], {}]], added: [['', {}]], removed: [['[0]', {}]] }

const result = getDiff(struct1, struct2)
const lodashResult = getDiff(struct1, struct2, { isLodashLike: true })

expect(result).toEqual(expectedResult)
expect(lodashResult).toEqual(expectedLodashResult)
})

test('Should return the difference between when many empty keys', () => {
const struct1 = { '': { '': '', a: { '': 'b' } } }
const struct2 = { '': { a: { '': '' } } }
const expectedResult: Delta = { edited: [['/a/', 'b', '']], added: [], removed: [['/', '']] }
const expectedLodashResult: Delta = { edited: [['.a.', 'b', '']], added: [], removed: [['.', '']] }

const result = getDiff(struct1, struct2)
const lodashResult = getDiff(struct1, struct2, { isLodashLike: true })
Expand Down
54 changes: 39 additions & 15 deletions src/core/get-struct-paths.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getStructPaths } from '.'
describe('GetStructPaths function', () => {
test('Should return all paths from a basic structure', () => {
const oldStruct = { 1: { 2: 7, 3: { 4: 6 } } }
const expectedResult = { '': '@{}', '1': '@{}', '1/2': 7, '1/3': '@{}', '1/3/4': 6 }
const expectedResult = { __root__: '@{}', '1': '@{}', '1/2': 7, '1/3': '@{}', '1/3/4': 6 }

const result = getStructPaths(oldStruct)

Expand All @@ -12,7 +12,7 @@ describe('GetStructPaths function', () => {

test('Should return path for root []', () => {
const oldStruct = [] as any
const expectedResult = { '': '@[]' }
const expectedResult = { __root__: '@[]' }

const result = getStructPaths(oldStruct)

Expand All @@ -21,7 +21,7 @@ describe('GetStructPaths function', () => {

test('Should return path for root {}', () => {
const oldStruct = {} as any
const expectedResult = { '': '@{}' }
const expectedResult = { __root__: '@{}' }

const result = getStructPaths(oldStruct)

Expand All @@ -31,7 +31,7 @@ describe('GetStructPaths function', () => {
test('Should return all paths containing Array property', () => {
const oldStruct = { a: 1, b: [{ c1: [{ c3: { c5: [1, 2, { c6: 3 }] } }, { c4: 6 }] }, { c2: 2 }] }
const expectedResult = {
'': '@{}',
__root__: '@{}',
a: 1,
b: '@[]',
'b/0[]': '@{}',
Expand All @@ -49,7 +49,7 @@ describe('GetStructPaths function', () => {
'b/1[]/c2': 2
}
const expectedLodashLikeResult = {
'': '@{}',
__root__: '@{}',
a: 1,
b: '@[]',
'b[0]': '@{}',
Expand All @@ -76,8 +76,32 @@ describe('GetStructPaths function', () => {

test('Should return paths when the values are objects', () => {
const oldStruct = { a: [], b: {} }
const expectedResult = { '': '@{}', a: [], b: {} }
const expectedLodashLikeResult = { '': '@{}', a: [], b: {} }
const expectedResult = { __root__: '@{}', a: [], b: {} }
const expectedLodashLikeResult = { __root__: '@{}', a: [], b: {} }

const result = getStructPaths(oldStruct)
const lodashLikeResult = getStructPaths(oldStruct, true)

expect(result).toEqual(expectedResult)
expect(lodashLikeResult).toEqual(expectedLodashLikeResult)
})

test('Should return paths when key in root is empty', () => {
const oldStruct = { '': 'cafe' }
const expectedResult = { __root__: '@{}', '': 'cafe' }
const expectedLodashLikeResult = { __root__: '@{}', '': 'cafe' }

const result = getStructPaths(oldStruct)
const lodashLikeResult = getStructPaths(oldStruct, true)

expect(result).toEqual(expectedResult)
expect(lodashLikeResult).toEqual(expectedLodashLikeResult)
})

test('Should return paths when nested empty keys', () => {
const oldStruct = { '': { '': 'cafe' } }
const expectedResult = { __root__: '@{}', '': '@{}', '/': 'cafe' }
const expectedLodashLikeResult = { __root__: '@{}', '': '@{}', '.': 'cafe' }

const result = getStructPaths(oldStruct)
const lodashLikeResult = getStructPaths(oldStruct, true)
Expand All @@ -89,10 +113,10 @@ describe('GetStructPaths function', () => {
test('Should return different paths when containing object and array with same key value at root', () => {
const oldStruct = { '0': 0 }
const newStruct = [0]
const expectedOldStructPaths = { '': '@{}', '0': 0 }
const expectedOldStructLodashLikePaths = { '': '@{}', '0': 0 }
const expectedNewStructPaths = { '': '@[]', '0[]': 0 }
const expectedNewStructLodashLikePaths = { '': '@[]', '[0]': 0 }
const expectedOldStructPaths = { __root__: '@{}', '0': 0 }
const expectedOldStructLodashLikePaths = { __root__: '@{}', '0': 0 }
const expectedNewStructPaths = { __root__: '@[]', '0[]': 0 }
const expectedNewStructLodashLikePaths = { __root__: '@[]', '[0]': 0 }

const oldStructPaths = getStructPaths(oldStruct)
const newStructPaths = getStructPaths(newStruct)
Expand All @@ -109,25 +133,25 @@ describe('GetStructPaths function', () => {
const oldStruct = { '0': [{ '0': 1 }] }
const newStruct = { '0': { '0': [1] } }
const expectedOldStructPaths = {
'': '@{}',
__root__: '@{}',
'0': '@[]',
'0/0[]': '@{}',
'0/0[]/0': 1
}
const expectedOldStructLodashLikePaths = {
'': '@{}',
__root__: '@{}',
'0': '@[]',
'0[0]': '@{}',
'0[0].0': 1
}
const expectedNewStructPaths = {
'': '@{}',
__root__: '@{}',
'0': '@{}',
'0/0': '@[]',
'0/0/0[]': 1
}
const expectedNewStructLodashLikePaths = {
'': '@{}',
__root__: '@{}',
'0': '@{}',
'0.0': '@[]',
'0.0[0]': 1
Expand Down
12 changes: 9 additions & 3 deletions src/core/get-struct-paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { StructPaths } from '../models/jsondiffer.model'
const generatePath = (isArray: boolean, currentPath: string, newPath: string, lodashLike: boolean): string => {
const prefix = lodashLike ? (isArray ? '[' : '.') : '/'
const suffix = lodashLike ? (isArray ? ']' : '') : isArray ? '[]' : ''
const path = currentPath !== '' ? `${currentPath}${prefix}${newPath}${suffix}` : `${lodashLike && isArray ? '[' : ''}${newPath}${suffix}`
const path =
currentPath === '__start__' ? `${lodashLike && isArray ? '[' : ''}${newPath}${suffix}` : `${currentPath}${prefix}${newPath}${suffix}`

return path
}
Expand All @@ -29,9 +30,14 @@ const generatePath = (isArray: boolean, currentPath: string, newPath: string, lo
* console.log(result)
* // Output: {"1": "@{}","1.2": null}
*/
export const getStructPaths = (struct: any, isLodashLike = false, paths?: { [key: string]: any }, currentPath = ''): StructPaths => {
export const getStructPaths = (
struct: any,
isLodashLike = false,
paths?: { [key: string]: any },
currentPath = '__start__'
): StructPaths => {
if (paths === undefined) {
paths = Array.isArray(struct) ? { '': '@[]' } : { '': '@{}' }
paths = Array.isArray(struct) ? { __root__: '@[]' } : { __root__: '@{}' }
}

for (const key of Object.keys(struct)) {
Expand Down

0 comments on commit ab9831e

Please sign in to comment.