Fixed #676: JSON Paths containing array properties with a `]` not parsed correctly
This commit is contained in:
parent
7c398aeef7
commit
3e7e1cebfd
|
@ -9,6 +9,8 @@ https://github.com/josdejong/jsoneditor
|
||||||
styling can be applied for default and non-default values. Thanks @AdamVig.
|
styling can be applied for default and non-default values. Thanks @AdamVig.
|
||||||
- Fixed #667: resolving JSON Schema examples and descriptions did not always
|
- Fixed #667: resolving JSON Schema examples and descriptions did not always
|
||||||
work for referenced schemas. Thanks @AdamVig.
|
work for referenced schemas. Thanks @AdamVig.
|
||||||
|
- Fixed #676: JSON Paths containing array properties with a `]` not parsed
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
|
||||||
## 2019-03-14, version 5.31.1
|
## 2019-03-14, version 5.31.1
|
||||||
|
|
|
@ -43,3 +43,10 @@ if (!Array.prototype.find) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Polyfill for String.trim
|
||||||
|
if (!String.prototype.trim) {
|
||||||
|
String.prototype.trim = function () {
|
||||||
|
return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -742,43 +742,75 @@ exports.isChildOf = function (elem, parent) {
|
||||||
* @return {Array}
|
* @return {Array}
|
||||||
*/
|
*/
|
||||||
exports.parsePath = function parsePath(jsonPath) {
|
exports.parsePath = function parsePath(jsonPath) {
|
||||||
var prop, remainder;
|
var path = [];
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
if (jsonPath.length === 0) {
|
function parseProperty () {
|
||||||
return [];
|
var prop = ''
|
||||||
}
|
while (jsonPath[i] !== undefined && /[\w$]/.test(jsonPath[i])) {
|
||||||
|
prop += jsonPath[i];
|
||||||
// find a match like '.prop'
|
i++;
|
||||||
var match = jsonPath.match(/^\.([\w$]+)/);
|
|
||||||
if (match) {
|
|
||||||
prop = match[1];
|
|
||||||
remainder = jsonPath.substr(prop.length + 1);
|
|
||||||
}
|
|
||||||
else if (jsonPath[0] === '[') {
|
|
||||||
// find a match like
|
|
||||||
var end = jsonPath.indexOf(']');
|
|
||||||
if (end === -1) {
|
|
||||||
throw new SyntaxError('Character ] expected in path');
|
|
||||||
}
|
|
||||||
if (end === 1) {
|
|
||||||
throw new SyntaxError('Index expected after [');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = jsonPath.substring(1, end);
|
if (prop === '') {
|
||||||
if (value[0] === '\'') {
|
throw new Error('Invalid JSON path: property name expected at index ' + i);
|
||||||
// ajv produces string prop names with single quotes, so we need
|
|
||||||
// to reformat them into valid double-quoted JSON strings
|
|
||||||
value = '\"' + value.substring(1, value.length - 1) + '\"';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prop = value === '*' ? value : JSON.parse(value); // parse string and number
|
return prop;
|
||||||
remainder = jsonPath.substr(end + 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new SyntaxError('Failed to parse path');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [prop].concat(parsePath(remainder))
|
function parseIndex (end) {
|
||||||
|
var name = ''
|
||||||
|
while (jsonPath[i] !== undefined && jsonPath[i] !== end) {
|
||||||
|
name += jsonPath[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonPath[i] !== end) {
|
||||||
|
throw new Error('Invalid JSON path: unexpected end, character ' + end + ' expected')
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (jsonPath[i] !== undefined) {
|
||||||
|
if (jsonPath[i] === '.') {
|
||||||
|
i++;
|
||||||
|
path.push(parseProperty());
|
||||||
|
}
|
||||||
|
else if (i > 0 && jsonPath[i] === '[') {
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (jsonPath[i] === '\'' || jsonPath[i] === '"') {
|
||||||
|
var end = jsonPath[i]
|
||||||
|
i++;
|
||||||
|
|
||||||
|
path.push(parseIndex(end));
|
||||||
|
|
||||||
|
if (jsonPath[i] !== end) {
|
||||||
|
throw new Error('Invalid JSON path: closing quote \' expected at index ' + i)
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var index = parseIndex(']').trim()
|
||||||
|
if (index.length === 0) {
|
||||||
|
throw new Error('Invalid JSON path: array value expected at index ' + i)
|
||||||
|
}
|
||||||
|
path.push(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonPath[i] !== ']') {
|
||||||
|
throw new Error('Invalid JSON path: closing bracket ] expected at index ' + i)
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error('Invalid JSON path: unexpected character "' + jsonPath[i] + '" at index ' + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -105,16 +105,19 @@ describe('util', function () {
|
||||||
assert.deepEqual(util.parsePath('.foo[2].bar'), ['foo', 2, 'bar']);
|
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 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 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.deepEqual(util.parsePath('.foo[*].bar'), ['foo', '*', 'bar']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it ('should throw an exception in case of an invalid path', function () {
|
it ('should throw an exception in case of an invalid path', function () {
|
||||||
assert.throws(function () {util.parsePath('.')}, /Error/);
|
assert.throws(function () {util.parsePath('.')}, /Invalid JSON path: property name expected at index 1/);
|
||||||
assert.throws(function () {util.parsePath('[')}, /Error/);
|
assert.throws(function () {util.parsePath('[')}, /Invalid JSON path: unexpected character "\[" at index 0/);
|
||||||
assert.throws(function () {util.parsePath('[]')}, /Error/);
|
assert.throws(function () {util.parsePath('[]')}, /Invalid JSON path: unexpected character "\[" at index 0/);
|
||||||
assert.throws(function () {util.parsePath('.[]')}, /Error/);
|
assert.throws(function () {util.parsePath('.foo[ ]')}, /Invalid JSON path: array value expected at index 7/);
|
||||||
assert.throws(function () {util.parsePath('["23]')}, /Error/);
|
assert.throws(function () {util.parsePath('.[]')}, /Invalid JSON path: property name expected at index 1/);
|
||||||
assert.throws(function () {util.parsePath('.foo bar')}, /Error/);
|
assert.throws(function () {util.parsePath('["23]')}, /Invalid JSON path: unexpected character "\[" at index 0/);
|
||||||
|
assert.throws(function () {util.parsePath('.foo bar')}, /Invalid JSON path: unexpected character " " at index 4/);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue