Skip to content

Instantly share code, notes, and snippets.

@john-yuan
Created July 13, 2019 08:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save john-yuan/be0dc5e56169177f69264b07b0b3e6a0 to your computer and use it in GitHub Desktop.
Save john-yuan/be0dc5e56169177f69264b07b0b3e6a0 to your computer and use it in GitHub Desktop.
A function to parse object path in JSON.
/**
* Parse the property path string.
*
* @param {string} path The property path.
* @returns {string[]} Returns the array of path.
*/
function parseObjectPath(path) {
var i = 0;
var l = path.length;
var ch;
var T_KEYWORD = 1;
var T_PROP_SQ = 2; // ['prop_name']
var T_PROP_DQ = 3; // ["prop_name"]
var T_PROP_NO = 4; // [1]
var type = T_KEYWORD;
var keywords = [];
var keywordBuffer = [];
var oneOf = function (ch, str) {
var j = 0;
var c = str.charAt(j);
while (c) {
if (c === ch) {
return true;
} else {
j += 1;
c = str.charAt(j);
}
}
return false;
};
var whitespace = function () {
while (i < l && oneOf(path.charAt(i), ' \r\n\t')) {
++i;
}
};
var unexpected = function (ch) {
throw new SyntaxError('unexpected token: ' + ch + ' at pos ' + i);
};
var read = function () {
return path.charAt(i);
};
var flushKeyword = function () {
var k = keywordBuffer.length;
var c;
while (k--) {
c = keywordBuffer[k];
if (oneOf(c, ' \t\r\n')) {
keywordBuffer.pop();
} else {
break;
}
}
k = keywordBuffer.join('');
k && keywords.push(k);
keywordBuffer = [];
};
var readNumber = function () {
var num = [];
while (true) {
ch = read();
if (oneOf(ch, '0123456789')) {
num.push(ch);
i += 1;
} else {
break;
}
if (i >= l) {
throw new SyntaxError('unexpected end');
}
}
return parseInt(num.join(''), 10);
};
var readString = function (qoute) {
var str = [];
while (true) {
ch = read();
i += 1;
if (ch === '\\') {
ch = read();
if (ch === qoute) {
str.push(ch);
i += 1;
} else if (ch === '\\') {
str.push(ch);
i += 1;
}
} else if (ch === qoute) {
break;
} else {
str.push(ch);
}
if (i >= l) {
throw new SyntaxError('unexpected end');
}
}
return str.join('');
};
whitespace();
ch = path.charAt(i);
if (ch === '.') {
unexpected(ch);
}
while (i < l) {
if (type === T_KEYWORD) {
ch = read();
if (ch === '[') {
flushKeyword();
i += 1;
whitespace();
ch = read();
if (ch === "'") {
i += 1;
type = T_PROP_SQ;
} else if (ch === '"') {
i += 1;
type = T_PROP_DQ;
} else if (ch === ']') {
unexpected(']');
} else {
type = T_PROP_NO;
}
} else if (ch === '.') {
flushKeyword();
i += 1;
whitespace();
ch = read();
if (oneOf(ch, '.[')) {
unexpected(ch);
}
} else {
keywordBuffer.push(ch);
i += 1;
}
} else if (type === T_PROP_SQ || type === T_PROP_DQ) {
keywords.push(readString(type === T_PROP_SQ ? "'" : '"'));
whitespace();
ch = read();
if (ch !== ']') {
unexpected(ch);
}
i += 1;
type = T_KEYWORD;
} else if (type === T_PROP_NO) {
keywords.push(readNumber());
whitespace();
ch = read();
if (ch !== ']') {
unexpected(ch);
}
i += 1;
type = T_KEYWORD;
}
}
flushKeyword();
return keywords;
}
// var keywords = parseObjectPath("['the-key-of-the-person-object'].skills[0][123123]");
// console.log(keywords);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment