From 9b051f8c2c8f0561137e5ab55bb1f8ae552fe6ac Mon Sep 17 00:00:00 2001 From: M66B Date: Sat, 29 Aug 2026 14:19:51 +0200 Subject: [PATCH] Added jpath operator --- FAQ.md | 1 + .../eu/faircode/email/ExpressionHelper.java | 43 +++++++++++++++++++ index.html | 1 + 3 files changed, 45 insertions(+) diff --git a/FAQ.md b/FAQ.md index 341f38a77e..9c8e12ba77 100644 --- a/FAQ.md +++ b/FAQ.md @@ -3026,6 +3026,7 @@ The following extra operators are available: * *contains* (string/array of strings contains substring) * *matches* (string/array of strings matches regex) * *startswith* / *endswith* (string/array of strings starting or ending with a string; since version 1.2233) +* *jpath* (string/array of JSON strings matching the [specified path](https://github.com/json-path/jsonpath); since version 1.2233) The following extra functions are available: diff --git a/app/src/main/java/eu/faircode/email/ExpressionHelper.java b/app/src/main/java/eu/faircode/email/ExpressionHelper.java index 94dcb2da6e..a93d39a275 100644 --- a/app/src/main/java/eu/faircode/email/ExpressionHelper.java +++ b/app/src/main/java/eu/faircode/email/ExpressionHelper.java @@ -37,6 +37,7 @@ import com.ezylang.evalex.operators.InfixOperator; import com.ezylang.evalex.parser.ASTNode; import com.ezylang.evalex.parser.ParseException; import com.ezylang.evalex.parser.Token; +import com.jayway.jsonpath.JsonPath; import org.json.JSONException; import org.json.JSONObject; @@ -123,6 +124,7 @@ public class ExpressionHelper { ContainsOperator oMatches = new ContainsOperator(true); StartsWithOperator oStartsWith = new StartsWithOperator(false); StartsWithOperator oEndsWith = new StartsWithOperator(true); + JPathOperator oJPath = new JPathOperator(); ExpressionConfiguration configuration = ExpressionConfiguration.defaultConfiguration(); @@ -142,6 +144,7 @@ public class ExpressionHelper { configuration.getOperatorDictionary().addOperator("Matches", oMatches); configuration.getOperatorDictionary().addOperator("StartsWith", oStartsWith); configuration.getOperatorDictionary().addOperator("EndsWith", oEndsWith); + configuration.getOperatorDictionary().addOperator("JPath", oJPath); Expression expression = new Expression(eval, configuration) .with("received", message == null ? null : message.received) @@ -640,4 +643,44 @@ public class ExpressionHelper { return expression.convertValue(result); } } + + @InfixOperator(precedence = OPERATOR_PRECEDENCE_COMPARISON) + public static class JPathOperator extends AbstractOperator { + JPathOperator() { + } + + @Override + public EvaluationValue evaluate( + Expression expression, Token operatorToken, EvaluationValue... operands) { + String result = null; + + try { + if (operands.length == 2) { + List array; + if (operands[0].getDataType() == EvaluationValue.DataType.ARRAY) + array = operands[0].getArrayValue(); + else + array = Arrays.asList(operands[0]); + + String path = operands[1].getStringValue(); + + if (array != null && !array.isEmpty() && !TextUtils.isEmpty(path)) + for (EvaluationValue item : array) { + String value = item.getStringValue(); + if (!TextUtils.isEmpty(value)) { + result = JsonPath.read(value, path); + break; + } + } + } + } catch (Throwable ex) { + Log.e("EXPR", ex); + } + + Log.i("EXPR " + operands[0] + "JSONPATH" + operands[1] + + " result=" + result); + + return expression.convertValue(result); + } + } } diff --git a/index.html b/index.html index 2b852dd9bf..f4a9627f90 100644 --- a/index.html +++ b/index.html @@ -1656,6 +1656,7 @@ X-Google-Original-From: Somebody <somebody+extra@example.org>
  • contains (string/array of strings contains substring)
  • matches (string/array of strings matches regex)
  • startswith / endswith (string/array of strings starting or ending with a string; since version 1.2233)
  • +
  • jpath (string/array of JSON strings matching the specified path; since version 1.2233)
  • The following extra functions are available: