Store conditional expression in database

conditionsjava8serialization

We have an application that allows users to enter conditionals in the form bound op x op bound2, we store this as a string, and then parse it at runtime to evaluate it.

It is a decent amount of work, for a very limited conditional statement.

We are looking for a way to serialize and then evaluate complex conditions, with at least a switch statement level of complexity.

I saw in this question How to serialize and deserialize lambda expression in F#? that in f# you can just serialize a lambda (and I assume that there is some way to get a lambda from a text string), but:

  1. We need to do this in Java
  2. I know that we can compile java code on the fly, and make it "safe" by stripping out keywords, and disallowing things like System. but even if its not a security nightmare, it is prohibitively computationally expensive to do thousands of times.

Does anyone know of a small language out there whose interpreter can do just the basics (conditionals, loops, variable assignment) and be run in/as java, or any way to run those types of expression as they are defined at runtime and need to be persisted.

Update: To be clear, the minimum functionality I need is an if else chain. I don't just need to evaluate one condition. The one condition is what I have now already.

Best Answer

You could also create a really simple expression language, and then evaluate it on the fly. Expression are trees, so it can be serialized as XML, JSON, s-expressions or whatever you prefer. Eg. a + b * c could be expressed in JSON as ["+", "a", ["*", "b", "c"]]. It is also really easy to write an evaluator for such a tree.

An if-chain like:

if a then x 
else if b then y
else if c then z
else q

Could be expressed in Json like:

["if", "a", "x", ["if", "b", "y", ["if", "c", "z", "q"]]]

An interpreter in pseudocode:

def eval(args):
  operator = args[0]
  if operator=="+":
    return eval(args[1]) + eval(args[2])
  elif operator =="*":
    return eval(args[1]) * eval(args[2])
  elif operator=="<":
    return eval(args[1]) < eval(args[2])
  elif operator=="if":
    if (eval(arg[1])):
        return eval(arg[2]) 
    else:
        return eval(arg[3])

And so on...

Of course, as soon as you add lambdas or functions it becomes much more complex, and then I would recommend using an off-the shelf scripting engine. But if you only need to support expressions, it might be simpler to just write your own evalator.

Related Topic