Fix JSON path parsing for array indices (#679)

* Switch JSON path tests to strict equality

The tests for `stringifyPath` and `parsePath` were using
[`assert.deepEqual`](https://nodejs.org/api/assert.html#assert_assert_deepequal_actual_expected_message),
which was causing the tests to pass when they should not have. Beyond
that, the `deepEqual` method is deprecated. The suggested replacement is
[`assert.deepStrictEqual`](https://nodejs.org/api/assert.html#assert_assert_deepstrictequal_actual_expected_message),
which causes the tests to fail where they should.

The difference between the two methods is the different between `==` and
`===`. `deepEqual` would coerce the input `"2"` to `2`, so the test was
passing even though the output was of the wrong type (string instead of
number).

* Coerce numeric indices to numbers in parsePath

This fixes a regression introduced in
3e7e1cebfd.
This commit is contained in:
Adam Vigneaux 2019-03-28 14:49:36 -04:00 committed by Jos de Jong
parent 560dd033ad
commit 09ab92017c
2 changed files with 20 additions and 18 deletions

View File

@ -797,6 +797,8 @@ exports.parsePath = function parsePath(jsonPath) {
if (index.length === 0) {
throw new Error('Invalid JSON path: array value expected at index ' + i)
}
// Coerce numeric indices to numbers, but ignore star
index = index === '*' ? index : JSON.parse(index);
path.push(index);
}

View File

@ -98,27 +98,27 @@ describe('util', function () {
describe('jsonPath', function () {
it('should stringify an array of paths', function() {
assert.deepEqual(util.stringifyPath([]), '');
assert.deepEqual(util.stringifyPath(['foo']), '.foo');
assert.deepEqual(util.stringifyPath(['foo', 'bar']), '.foo.bar');
assert.deepEqual(util.stringifyPath(['foo', 2]), '.foo[2]');
assert.deepEqual(util.stringifyPath(['foo', 2, 'bar']), '.foo[2].bar');
assert.deepEqual(util.stringifyPath(['foo', 2, 'bar_baz']), '.foo[2].bar_baz');
assert.deepEqual(util.stringifyPath(['foo', 'prop-with-hyphens']), '.foo["prop-with-hyphens"]');
assert.deepEqual(util.stringifyPath(['foo', 'prop with spaces']), '.foo["prop with spaces"]');
assert.deepStrictEqual(util.stringifyPath([]), '');
assert.deepStrictEqual(util.stringifyPath(['foo']), '.foo');
assert.deepStrictEqual(util.stringifyPath(['foo', 'bar']), '.foo.bar');
assert.deepStrictEqual(util.stringifyPath(['foo', 2]), '.foo[2]');
assert.deepStrictEqual(util.stringifyPath(['foo', 2, 'bar']), '.foo[2].bar');
assert.deepStrictEqual(util.stringifyPath(['foo', 2, 'bar_baz']), '.foo[2].bar_baz');
assert.deepStrictEqual(util.stringifyPath(['foo', 'prop-with-hyphens']), '.foo["prop-with-hyphens"]');
assert.deepStrictEqual(util.stringifyPath(['foo', 'prop with spaces']), '.foo["prop with spaces"]');
})
it ('should parse a json path', function () {
assert.deepEqual(util.parsePath(''), []);
assert.deepEqual(util.parsePath('.foo'), ['foo']);
assert.deepEqual(util.parsePath('.foo.bar'), ['foo', 'bar']);
assert.deepEqual(util.parsePath('.foo[2]'), ['foo', 2]);
assert.deepEqual(util.parsePath('.foo[2].bar'), ['foo', 2, 'bar']);
assert.deepEqual(util.parsePath('.foo["prop with spaces"]'), ['foo', 'prop with spaces']);
assert.deepEqual(util.parsePath('.foo[\'prop with single quotes as outputted by ajv library\']'), ['foo', 'prop with single quotes as outputted by ajv library']);
assert.deepEqual(util.parsePath('.foo["prop with . dot"]'), ['foo', 'prop with . dot']);
assert.deepEqual(util.parsePath('.foo["prop with ] character"]'), ['foo', 'prop with ] character']);
assert.deepEqual(util.parsePath('.foo[*].bar'), ['foo', '*', 'bar']);
assert.deepStrictEqual(util.parsePath(''), []);
assert.deepStrictEqual(util.parsePath('.foo'), ['foo']);
assert.deepStrictEqual(util.parsePath('.foo.bar'), ['foo', 'bar']);
assert.deepStrictEqual(util.parsePath('.foo[2]'), ['foo', 2]);
assert.deepStrictEqual(util.parsePath('.foo[2].bar'), ['foo', 2, 'bar']);
assert.deepStrictEqual(util.parsePath('.foo["prop with spaces"]'), ['foo', 'prop with spaces']);
assert.deepStrictEqual(util.parsePath('.foo[\'prop with single quotes as outputted by ajv library\']'), ['foo', 'prop with single quotes as outputted by ajv library']);
assert.deepStrictEqual(util.parsePath('.foo["prop with . dot"]'), ['foo', 'prop with . dot']);
assert.deepStrictEqual(util.parsePath('.foo["prop with ] character"]'), ['foo', 'prop with ] character']);
assert.deepStrictEqual(util.parsePath('.foo[*].bar'), ['foo', '*', 'bar']);
});
it ('should throw an exception in case of an invalid path', function () {