Skip to content

Commit da006dc

Browse files
author
Christoffer Haglund
committed
Update dependencies to use jsonpath-plus and refactor JSONPath handling
1 parent 32045c4 commit da006dc

3 files changed

Lines changed: 84 additions & 162 deletions

File tree

js/package-lock.json

Lines changed: 44 additions & 153 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,10 @@
2929
},
3030
"dependencies": {
3131
"fast-json-patch": "^3.1.1",
32-
"jsonpath": "^1.1.1"
32+
"jsonpath-plus": "^10.4.0"
3333
},
3434
"devDependencies": {
3535
"@types/chai": "^4.3.4",
36-
"@types/jsonpath": "^0.2.0",
3736
"@types/mocha": "^10.0.1",
3837
"chai": "^4.3.7",
3938
"mocha": "^10.2.0",

js/src/index.ts

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import jsonpatch, { Operation } from 'fast-json-patch'
2-
import jp from 'jsonpath'
2+
import { JSONPath } from 'jsonpath-plus'
33

44
// Export to help dependencies because this is used in our interface.
55
export { Operation } from 'fast-json-patch'
@@ -101,10 +101,14 @@ export class Basin<T> {
101101
delete cursor.d
102102
}
103103

104-
const expressions = jp.parse(cursor.jsonPath!)
105-
for (const expression of expressions) {
106-
if (expression.expression.type !== 'root') {
107-
this._keys.set(label, expression.expression.value)
104+
if (!cursor.jsonPath!.startsWith('$')) {
105+
cursor.jsonPath = '$.' + cursor.jsonPath
106+
}
107+
108+
const pathArray = JSONPath.toPathArray(cursor.jsonPath!)
109+
for (const segment of pathArray) {
110+
if (segment !== '$') {
111+
this._keys.set(label, segment)
108112
break
109113
}
110114
}
@@ -123,9 +127,9 @@ export class Basin<T> {
123127
const jsonPath = cursor.jsonPath!
124128
if (typeof position !== 'number') {
125129
// Set the value.
126-
jp.value(this.items, jsonPath, value)
130+
jpValue(this.items, jsonPath, value)
127131
} else {
128-
jp.apply(this.items, jsonPath, (currentValue: string) => {
132+
jpApply(this.items, jsonPath, (currentValue: string) => {
129133
if (Array.isArray(currentValue)) {
130134
if (cursor.deleteCount !== undefined) {
131135
// Delete
@@ -156,4 +160,32 @@ export class Basin<T> {
156160
const key = this._keys.get(cursorLabel)!
157161
return this.items[key]
158162
}
163+
}
164+
165+
function jpValue(obj: any, path: string, value: any): void {
166+
const results: any[] = JSONPath({ path, json: obj, resultType: 'all' })
167+
if (results.length > 0) {
168+
results[0].parent[results[0].parentProperty] = value
169+
} else {
170+
// Path doesn't exist yet — create intermediate objects and set the value.
171+
const pathArray = JSONPath.toPathArray(path)
172+
let current = obj
173+
for (let i = 1; i < pathArray.length - 1; i++) {
174+
const key = pathArray[i]
175+
if (current[key] === undefined) {
176+
current[key] = {}
177+
}
178+
current = current[key]
179+
}
180+
if (pathArray.length > 1) {
181+
current[pathArray[pathArray.length - 1]] = value
182+
}
183+
}
184+
}
185+
186+
function jpApply(obj: any, path: string, fn: (value: any) => any): void {
187+
const results: any[] = JSONPath({ path, json: obj, resultType: 'all' })
188+
for (const result of results) {
189+
result.parent[result.parentProperty] = fn(result.value)
190+
}
159191
}

0 commit comments

Comments
 (0)