Skip to content

Commit

Permalink
fix: correctly handle property names containing spaces and special ch…
Browse files Browse the repository at this point in the history
…aracters in JMESPath
  • Loading branch information
josdejong committed Oct 17, 2022
1 parent d7882ee commit 8e7d3e8
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
40 changes: 40 additions & 0 deletions src/lib/plugins/query/jmespathQueryLanguage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,46 @@ describe('jmespathQueryLanguage', () => {
})
})

it('should correctly escape and quote sort and projection fields', () => {
const item42 = {
id: 42,
nested: {
'complex "field" \'name\'': 42
}
}
const item0 = {
id: 0,
nested: {
'complex "field" \'name\'': 0
}
}
const json = [item42, item0]
console.log(json)
const query = createQuery(json, {
sort: {
path: ['nested', 'complex "field" \'name\''],
direction: 'asc'
},
projection: {
paths: [['id'], ['nested', 'complex "field" \'name\'']]
}
})

assert.deepStrictEqual(
query,
'[*] ' +
'| sort_by(@, &nested."complex \\"field\\" \'name\'") ' +
'| [*].{id: id, "complex \\"field\\" \'name\'": nested."complex \\"field\\" \'name\'"}'
)

const result = executeQuery(json, query)

assert.deepStrictEqual(result, [
{ id: 0, 'complex "field" \'name\'': 0 },
{ id: 42, 'complex "field" \'name\'': 42 }
])
})

it('should return null when property is not found', () => {
const query = '@.foo'
const data = {}
Expand Down
10 changes: 6 additions & 4 deletions src/lib/plugins/query/jmespathQueryLanguage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ function createQuery(json: JSONValue, queryOptions: QueryLanguageOptions): strin
projection.paths
.map((path) => {
const name = path[path.length - 1]
return name + ': ' + stringifyPathForJmespath(path)
return stringifyProp(name) + ': ' + stringifyPathForJmespath(path)
})
.join(', ') +
'}'
Expand Down Expand Up @@ -112,10 +112,8 @@ export function stringifyPathForJmespath(path: JSONPath): string {
.map((prop) => {
if (typeof prop === 'number') {
return '[' + prop + ']'
} else if (typeof prop === 'string' && prop.match(/^[A-Za-z\d_$]+$/)) {
return '.' + prop
} else {
return '."' + String(prop) + '"'
return '.' + stringifyProp(String(prop))
}
})
.join('')
Expand All @@ -124,3 +122,7 @@ export function stringifyPathForJmespath(path: JSONPath): string {
? str.slice(1) // remove first dot
: str
}

function stringifyProp(prop: string): string {
return prop.match(/^[A-Za-z\d_$]+$/) ? prop : JSON.stringify(prop)
}

0 comments on commit 8e7d3e8

Please sign in to comment.