Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse complex String Expression to Boolean in Javascript

I've got the Task to write a filter for complex and nested JSONs. To do this I need to evaluate Boolean Expressions which the user enters in an input field. For the sake of the question lets say we have got the following input:

(Key1 = "foo" || key2 = 2 && key3 = "bar") && key4 = 7

I managed to write a function to evaluate each keyValue-Pair to a either "True" or "False" and replaced them in the string: e.g.:

(True || False && True) && True

Now I want to parse this String to a boolean Expression. Is there any "easy" way (built in Function, Plugin) for Javascript which can parse this String?

like image 516
GuyWithCookies Avatar asked Aug 16 '16 08:08

GuyWithCookies


2 Answers

There's eval() which is usually not recommended to use but maybe in your case it's suitable. See for more details: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval

You could write:

eval("(true || false && true) && true") // Returns: 1

Note, that I had to rewrite True to true because True is not a recognised as a boolean expression.

However, scopes are applied to eval() so I could also write:

var True = 1;
var False = 0;
eval("(True || False && True) && True"); // Returns: 1

This could work for you if you know the variables in advance I guess. Otherwise, maybe have a look at https://silentmatt.com/javascript-expression-evaluator/ or http://jsep.from.so/.

like image 146
martin Avatar answered Sep 18 '22 17:09

martin


https://github.com/joewalnes/filtrex

A simple, safe, JavaScript Filter Expression compiler for end-users

// Input from user (e.g. search filter)
var expression = '(key1 == "foo" || key2 == 2 && key3 == "bar") && key4 == 7';

// Compile expression to executable function
var myfilter = compileExpression(expression);

// Execute function
myfilter({Key1: "foo", key2: 2, key3: "bar", key4: 7}); // returns 1
myfilter({}); // returns 0

// filter an array of objects
var data = [{key1: "foo"}, {key1: "foo2"}];
var results = data.filter(myfilter);

the cost of this beauty: 92KByte minified bundle size

i started the project logic_fn, to do a similar job in a 1KByte minified bundle, by translating a custom logic expression (with custom operators like &, AND, -) to a javascript expression string, and feeding that to var f = new Function('input', 'return ' + expression + ';'). new Function is a bit more secure than eval, but i still must defend against arbitrary code execution attacks.

like image 30
Mila Nautikus Avatar answered Sep 20 '22 17:09

Mila Nautikus