Я хотел эквивалент * Python ast.literal_eval
для Javascript - что-то, что могло бы анализировать только литеральные объекты, такие как JSON, но позволяло использовать удобные ключи без кавычек Javascript. (Это для ввода данных человеком; простота и строгость стандартного JSON предпочтительнее для отправки данных между серверами.)
Это также то, что хотел оригинальный постер, поэтому я выложу свое решение здесь. Я использовал библиотеку Esprima для построения абстрактного синтаксического дерева, а затем преобразовал дерево в объекты, например:
function literal_eval(object_str) {
var ast = esprima.parse("var dummy = " + object_str);
if (ast.body.length != 1 || ast.body[0].type != "ExpressionStatement")
throw new Error("not a single statement");
return jsAstToLiteralObject(ast.body[0].expression.right);
}
function jsAstToLiteralObject(ast) {
if (ast.type == "Literal")
return ast.value;
else if (ast.type == "ArrayExpression") {
var out = [];
for (var i in ast.elements)
out.push(jsAstToLiteralObject(ast.elements[i]));
return out;
}
else if (ast.type == "ObjectExpression") {
var out = {};
for (var k in ast.properties) {
var key;
if (ast.properties[k].type == "Property" &&
ast.properties[k].key.type == "Literal" &&
typeof ast.properties[k].key.value == "string")
key = ast.properties[k].key.value;
else if (ast.properties[k].type == "Property" &&
ast.properties[k].key.type == "Identifier")
key = ast.properties[k].key.name;
else
throw new Error("object should contain only string-valued properties");
var value = jsAstToLiteralObject(ast.properties[k].value);
out[key] = value;
}
return out;
}
else
throw new Error("not a literal expression");
}
"var dummy = " +
необходим для того, чтобы Esprima интерпретировала начальный символ {
как начало выражения объекта, а не как блок кода.
Ни в коем случае не оценивается object_str
напрямую, поэтому вы не можете проникнуть во вредоносный код.
В качестве дополнительного преимущества пользователи могут также добавлять комментарии в object_str
.
Для такой проблемы также стоит рассмотреть YAML . Однако мне нужен настоящий синтаксис Javascript, потому что я интегрирую его с другими объектами ввода данных в формате Javascript (поэтому у меня были другие причины для включения библиотеки Esprima).