0

I have an expression in String format.

String exp = "(weight > 50 && height > 150 && height < 160) || BP = 130";

I created this string from a JSON object. So it is flexible to convert to any format.

And now I have one user's data in JSON format.

{
  "weight": 55,
  "height": 155,
  "BP": 130
}

How will I validate the user;s JSON details against the above expression. I am expecting a true/false result based on the expression validation.

Naman
  • 27,789
  • 26
  • 218
  • 353
skmaran.nr.iras
  • 8,152
  • 28
  • 81
  • 116
  • I got the exact answer from that one. ExecutableStatement statement = (ExecutableStatement) MVEL.compileExpression(ruleExpression.toString()); Boolean result = (Boolean) MVEL.executeExpression(statement, user);} – skmaran.nr.iras Dec 15 '19 at 18:05

1 Answers1

1

It should probably be unsurprising for you to learn that there is no such thing to do exactly what you want. You will have to write it yourself.

There are two main steps: a parser and an interpreter. The logical way to structure this code is by using the interpreter pattern.

You should build up a sequence of expressions, each of which is capable of saying whether it matches the given json.

interface Expression {
    boolean matches(JsonObject json);
}

For your example, you will need a:

  • Greater than expression (key > val)
  • Less than expression (key < val)
  • Equals expression (key = val)
  • And expression (expr && expr2)
  • Or expression (expr || expr2)

The parentheses do not need an expression of their own.

Here is an example of how the And expression would look. It simply defers to two delegates and performs a logical and.

The following code all assumes the use of Gson, but you can use any json parsing library.

class AndExpression implements Expression {
    private final Expression a;
    private final Expression b;

    AndExpression(Expression a, Expression b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public boolean matches(JsonObject json) {
        return a.matches(json) && b.matches(json);
    }
}

The equals expression is a bit more complex. It needs to look for existence of the key, obtain the value, and the perform the comparison.

class EqualsExpression implements Expression {
    private final String key;
    private final String value;

    EqualsExpression(String key, String value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public boolean matches(JsonObject json) {
        if (json.has(key)) {
            final JsonElement elem = json.get(key);
            if (elem.isJsonPrimitive()) {
                return elem.getAsJsonPrimitive().getAsString().equals(value);
            }
        }
        return false;
    }
}

To model the expression foo = bar && bar = baz you could compose these two classes together like this:

Expression fullExpression = new AndExpression(
    new EqualsExpression("foo", "bar"),
    new EqualsExpression("bar", "baz")
);

You would need to implement the other 3 expressions, which should be trivial based on what I've given you, and a parser to create and compose the expressions dynamically based on your text input.

Michael
  • 41,989
  • 11
  • 82
  • 128