From 5bf050b74abcfd5ddbccad05580f12a71cfc04c3 Mon Sep 17 00:00:00 2001 From: Guido Breitenhuber Date: Wed, 12 Nov 2025 21:59:29 +0100 Subject: [PATCH 1/2] Construct JSON path only on exceptional cases. --- .../github/jamsesso/jsonlogic/JsonLogic.java | 8 +- .../jsonlogic/JsonLogicException.java | 35 +++-- .../ast/JsonLogicParseException.java | 4 + .../jsonlogic/ast/JsonLogicParser.java | 33 +++-- .../JsonLogicEvaluationException.java | 11 ++ .../evaluator/JsonLogicEvaluator.java | 135 ++++++++++++++---- .../evaluator/expressions/AllExpression.java | 27 ++-- .../expressions/ArrayHasExpression.java | 30 ++-- .../expressions/FilterExpression.java | 29 ++-- .../evaluator/expressions/IfExpression.java | 56 ++++++-- .../expressions/InequalityExpression.java | 6 +- .../JsonPathHandlerJsonLogicExpression.java | 20 +++ .../expressions/LogicExpression.java | 20 ++- .../evaluator/expressions/MapExpression.java | 24 +++- .../expressions/ReduceExpression.java | 35 +++-- 15 files changed, 369 insertions(+), 104 deletions(-) create mode 100644 src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/JsonPathHandlerJsonLogicExpression.java diff --git a/src/main/java/io/github/jamsesso/jsonlogic/JsonLogic.java b/src/main/java/io/github/jamsesso/jsonlogic/JsonLogic.java index fa25f2f..3cf2351 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/JsonLogic.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/JsonLogic.java @@ -2,6 +2,7 @@ import io.github.jamsesso.jsonlogic.ast.JsonLogicNode; import io.github.jamsesso.jsonlogic.ast.JsonLogicParser; +import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluationException; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluator; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicExpression; import io.github.jamsesso.jsonlogic.evaluator.expressions.*; @@ -84,7 +85,12 @@ public Object apply(String json, Object data) throws JsonLogicException { evaluator = new JsonLogicEvaluator(expressions); } - return evaluator.evaluate(parseCache.get(json), data, "$"); + try { + return evaluator.evaluate(parseCache.get(json), data, ""); + } catch (JsonLogicException e) { + e.prependPartialJsonPath("$"); + throw e; + } } public static boolean truthy(Object value) { diff --git a/src/main/java/io/github/jamsesso/jsonlogic/JsonLogicException.java b/src/main/java/io/github/jamsesso/jsonlogic/JsonLogicException.java index 0e34710..ee654b2 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/JsonLogicException.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/JsonLogicException.java @@ -2,28 +2,47 @@ public class JsonLogicException extends Exception { - private String jsonPath; + private final StringBuilder jsonPath = new StringBuilder(); private JsonLogicException() { // The default constructor should not be called for exceptions. A reason must be provided. } + public JsonLogicException(String msg) { + super(msg); + } + public JsonLogicException(String msg, String jsonPath) { - super(msg); - this.jsonPath = jsonPath; + super(msg); + prependPartialJsonPath(jsonPath); } + public JsonLogicException(Throwable cause) { + super(cause); + } + public JsonLogicException(Throwable cause, String jsonPath) { - super(cause); - this.jsonPath = jsonPath; + super(cause); + prependPartialJsonPath(jsonPath); } + public JsonLogicException(String msg, Throwable cause) { + super(msg, cause); + } + public JsonLogicException(String msg, Throwable cause, String jsonPath) { super(msg, cause); - this.jsonPath = jsonPath; + prependPartialJsonPath(jsonPath); } - public String getJsonPath() { - return jsonPath; + public String getJsonPath() { + return jsonPath.toString(); } + + public void prependPartialJsonPath(String partialPath) { + if (partialPath == null) { + return; + } + jsonPath.insert(0, partialPath); + } } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParseException.java b/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParseException.java index 8bc5873..88547da 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParseException.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParseException.java @@ -14,4 +14,8 @@ public JsonLogicParseException(Throwable cause, String jsonPath) { public JsonLogicParseException(String msg, Throwable cause, String jsonPath) { super(msg, cause, jsonPath); } + + public JsonLogicParseException(String msg) { + super(msg); + } } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParser.java b/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParser.java index bf442b8..66f7856 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParser.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParser.java @@ -17,15 +17,16 @@ public static JsonLogicNode parse(String json) throws JsonLogicParseException { try { return parse(PARSER.parse(json)); } + catch (JsonLogicParseException e) { + e.prependPartialJsonPath("$"); + throw e; + } catch (JsonSyntaxException e) { throw new JsonLogicParseException(e, "$"); } } private static JsonLogicNode parse(JsonElement root) throws JsonLogicParseException { - return parse(root, "$"); - } - private static JsonLogicNode parse(JsonElement root, String jsonPath) throws JsonLogicParseException { // Handle null if (root.isJsonNull()) { return JsonLogicNull.NULL; @@ -56,9 +57,16 @@ private static JsonLogicNode parse(JsonElement root, String jsonPath) throws Jso JsonArray array = root.getAsJsonArray(); List elements = new ArrayList<>(array.size()); - int index = 0; - for (JsonElement element : array) { - elements.add(parse(element, String.format("%s[%d]", jsonPath, index++))); + for (int index = 0; index < array.size(); index++) { + JsonElement element = array.get(index); + JsonLogicNode arrayNode; + try { + arrayNode = parse(element); + } catch (JsonLogicParseException e) { + e.prependPartialJsonPath("[" + (index) + "]"); + throw e; + } + elements.add(arrayNode); } return new JsonLogicArray(elements); @@ -68,14 +76,21 @@ private static JsonLogicNode parse(JsonElement root, String jsonPath) throws Jso JsonObject object = root.getAsJsonObject(); if (object.keySet().size() != 1) { - throw new JsonLogicParseException("objects must have exactly 1 key defined, found " + object.keySet().size(), jsonPath); + throw new JsonLogicParseException("objects must have exactly 1 key defined, found " + object.keySet().size()); } String key = object.keySet().stream().findAny().get(); - JsonLogicNode argumentNode = parse(object.get(key), String.format("%s.%s", jsonPath, key)); + JsonLogicNode argumentNode; JsonLogicArray arguments; - // Always coerce single-argument operations into a JsonLogicArray with a single element. + try { + argumentNode = parse(object.get(key)); + } catch (JsonLogicParseException e) { + e.prependPartialJsonPath("." + key); + throw e; + } + + // Always coerce single-argument operations into a JsonLogicArray with a single element. if (argumentNode instanceof JsonLogicArray) { arguments = (JsonLogicArray) argumentNode; } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluationException.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluationException.java index b35d2bc..8f5723f 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluationException.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluationException.java @@ -3,14 +3,25 @@ import io.github.jamsesso.jsonlogic.JsonLogicException; public class JsonLogicEvaluationException extends JsonLogicException { + public JsonLogicEvaluationException(String msg) { + super(msg); + } public JsonLogicEvaluationException(String msg, String jsonPath) { super(msg, jsonPath); } + public JsonLogicEvaluationException(Throwable cause) { + super(cause); + } + public JsonLogicEvaluationException(Throwable cause, String jsonPath) { super(cause, jsonPath); } + public JsonLogicEvaluationException(String msg, Throwable cause) { + super(msg, cause); + } + public JsonLogicEvaluationException(String msg, Throwable cause, String jsonPath) { super(msg, cause, jsonPath); } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluator.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluator.java index e15fbb0..722bd24 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluator.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluator.java @@ -1,5 +1,6 @@ package io.github.jamsesso.jsonlogic.evaluator; +import io.github.jamsesso.jsonlogic.JsonLogicException; import io.github.jamsesso.jsonlogic.ast.*; import io.github.jamsesso.jsonlogic.utils.ArrayLike; @@ -24,15 +25,31 @@ public JsonLogicEvaluator(Map expressions) { this.expressions = Collections.unmodifiableMap(expressions); } + @Deprecated public Object evaluate(JsonLogicNode node, Object data, String jsonPath) throws JsonLogicEvaluationException { - switch (node.getType()) { - case PRIMITIVE: return evaluate((JsonLogicPrimitive) node); - case VARIABLE: return evaluate((JsonLogicVariable) node, data, jsonPath + ".var"); - case ARRAY: return evaluate((JsonLogicArray) node, data, jsonPath); - default: return evaluate((JsonLogicOperation) node, data, jsonPath); - } + try { + return evaluate(node, data); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath(jsonPath); + throw e; + } } + public Object evaluate(JsonLogicNode node, Object data) throws JsonLogicEvaluationException { + switch (node.getType()) { + case PRIMITIVE: return evaluate((JsonLogicPrimitive) node); + case VARIABLE: + try { + return evaluate((JsonLogicVariable) node, data); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath(".var"); + throw e; + } + case ARRAY: return evaluate((JsonLogicArray) node, data); + default: return evaluate((JsonLogicOperation) node, data); + } + } + public Object evaluate(JsonLogicPrimitive primitive) { switch (primitive.getPrimitiveType()) { case NUMBER: return ((JsonLogicNumber) primitive).getValue(); @@ -42,20 +59,53 @@ public Object evaluate(JsonLogicPrimitive primitive) { } } - public Object evaluate(JsonLogicVariable variable, Object data, String jsonPath) + @Deprecated + public Object evaluate(JsonLogicVariable variable, Object data, String jsonPath) + throws JsonLogicEvaluationException { + try { + return evaluate(variable, data); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath(jsonPath); + throw e; + } + } + + public Object evaluate(JsonLogicVariable variable, Object data) throws JsonLogicEvaluationException { - Object defaultValue = evaluate(variable.getDefaultValue(), null, jsonPath + "[1]"); + Object defaultValue; + + try { + defaultValue = evaluate(variable.getDefaultValue(), null, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[1]"); + throw e; + } - if (data == null) { + if (data == null) { return defaultValue; } - Object key = evaluate(variable.getKey(), data, jsonPath + "[0]"); + Object key; + + try { + key = evaluate(variable.getKey(), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } - if (key == null) { - return Optional.of(data) + if (key == null) { + Object varValue; + try { + varValue = evaluate(variable.getDefaultValue(), null, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } + + return Optional.of(data) .map(JsonLogicEvaluator::transform) - .orElse(evaluate(variable.getDefaultValue(), null, jsonPath + "[1]")); + .orElse(varValue); } if (key instanceof Number) { @@ -84,9 +134,14 @@ public Object evaluate(JsonLogicVariable variable, Object data, String jsonPath) Object result = data; for (String partial : keys) { - result = evaluatePartialVariable(partial, result, jsonPath + "[0]"); - - if (result == MISSING) { + try { + result = evaluatePartialVariable(partial, result); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } + + if (result == MISSING) { return defaultValue; } else if (result == null) { return null; @@ -96,10 +151,10 @@ public Object evaluate(JsonLogicVariable variable, Object data, String jsonPath) return result; } - throw new JsonLogicEvaluationException("var first argument must be null, number, or string", jsonPath + "[0]"); + throw new JsonLogicEvaluationException("var first argument must be null, number, or string", "[0]"); } - private Object evaluatePartialVariable(String key, Object data, String jsonPath) throws JsonLogicEvaluationException { + private Object evaluatePartialVariable(String key, Object data) throws JsonLogicEvaluationException { if (ArrayLike.isEligible(data)) { ArrayLike list = new ArrayLike(data); int index; @@ -108,7 +163,7 @@ private Object evaluatePartialVariable(String key, Object data, String jsonPath) index = Integer.parseInt(key); } catch (NumberFormatException e) { - throw new JsonLogicEvaluationException(e, jsonPath); + throw new JsonLogicEvaluationException(e); } if (index < 0 || index >= list.size()) { @@ -130,25 +185,55 @@ private Object evaluatePartialVariable(String key, Object data, String jsonPath) return null; } - public List evaluate(JsonLogicArray array, Object data, String jsonPath) throws JsonLogicEvaluationException { + @Deprecated + public List evaluate(JsonLogicArray array, Object data, String jsonPath) throws JsonLogicEvaluationException { + try { + return evaluate(array, data); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath(jsonPath); + throw e; + } + } + + public List evaluate(JsonLogicArray array, Object data) throws JsonLogicEvaluationException { List values = new ArrayList<>(array.size()); - int index = 0; - for(JsonLogicNode element : array) { - values.add(evaluate(element, data, String.format("%s[%d]", jsonPath, index++))); + for(int index = 0; index < array.size(); index++) { + JsonLogicNode element = array.get(index); + try { + values.add(evaluate(element, data, "")); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[" + index + "]"); + throw e; + } } return values; } + @Deprecated public Object evaluate(JsonLogicOperation operation, Object data, String jsonPath) throws JsonLogicEvaluationException { + try { + return evaluate(operation, data); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath(jsonPath); + throw e; + } + } + + public Object evaluate(JsonLogicOperation operation, Object data) throws JsonLogicEvaluationException { JsonLogicExpression handler = expressions.get(operation.getOperator()); if (handler == null) { - throw new JsonLogicEvaluationException("Undefined operation '" + operation.getOperator() + "'", jsonPath); + throw new JsonLogicEvaluationException("Undefined operation '" + operation.getOperator() + "'"); } - return handler.evaluate(this, operation.getArguments(), data, String.format("%s.%s", jsonPath, operation.getOperator())); + try { + return handler.evaluate(this, operation.getArguments(), data, ""); + } catch (JsonLogicException e) { + e.prependPartialJsonPath("." + operation.getOperator()); + throw e; + } } public static Object transform(Object value) { diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/AllExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/AllExpression.java index 2e9350f..04d9900 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/AllExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/AllExpression.java @@ -1,13 +1,13 @@ package io.github.jamsesso.jsonlogic.evaluator.expressions; +import io.github.jamsesso.jsonlogic.JsonLogic; import io.github.jamsesso.jsonlogic.ast.JsonLogicArray; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluationException; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluator; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicExpression; import io.github.jamsesso.jsonlogic.utils.ArrayLike; -import io.github.jamsesso.jsonlogic.JsonLogic; -public class AllExpression implements JsonLogicExpression { +public class AllExpression extends JsonPathHandlerJsonLogicExpression implements JsonLogicExpression { public static final AllExpression INSTANCE = new AllExpression(); private AllExpression() { @@ -20,20 +20,26 @@ public String key() { } @Override - public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data, String jsonPath) + public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) throws JsonLogicEvaluationException { if (arguments.size() != 2) { - throw new JsonLogicEvaluationException("all expects exactly 2 arguments", jsonPath); + throw new JsonLogicEvaluationException("all expects exactly 2 arguments"); } - Object maybeArray = evaluator.evaluate(arguments.get(0), data, jsonPath + "[0]"); + Object maybeArray; + try { + maybeArray = evaluator.evaluate(arguments.get(0), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } if (maybeArray == null) { return false; } if (!ArrayLike.isEligible(maybeArray)) { - throw new JsonLogicEvaluationException("first argument to all must be a valid array", jsonPath); + throw new JsonLogicEvaluationException("first argument to all must be a valid array"); } ArrayLike array = new ArrayLike(maybeArray); @@ -44,8 +50,13 @@ public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, O int index = 1; for (Object item : array) { - if(!JsonLogic.truthy(evaluator.evaluate(arguments.get(1), item, String.format("%s[%d]", jsonPath, index)))) { - return false; + try { + if (!JsonLogic.truthy(evaluator.evaluate(arguments.get(1), item, ""))) { + return false; + } + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[" + index + "]"); + throw e; } } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ArrayHasExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ArrayHasExpression.java index 7d9bb14..8504e9f 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ArrayHasExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ArrayHasExpression.java @@ -1,13 +1,13 @@ package io.github.jamsesso.jsonlogic.evaluator.expressions; +import io.github.jamsesso.jsonlogic.JsonLogic; import io.github.jamsesso.jsonlogic.ast.JsonLogicArray; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluationException; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluator; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicExpression; import io.github.jamsesso.jsonlogic.utils.ArrayLike; -import io.github.jamsesso.jsonlogic.JsonLogic; -public class ArrayHasExpression implements JsonLogicExpression { +public class ArrayHasExpression extends JsonPathHandlerJsonLogicExpression implements JsonLogicExpression { public static final ArrayHasExpression SOME = new ArrayHasExpression(true); public static final ArrayHasExpression NONE = new ArrayHasExpression(false); @@ -23,13 +23,20 @@ public String key() { } @Override - public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data, String jsonPath) + public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) throws JsonLogicEvaluationException { if (arguments.size() != 2) { - throw new JsonLogicEvaluationException(key() + " expects exactly 2 arguments", jsonPath); + throw new JsonLogicEvaluationException(key() + " expects exactly 2 arguments"); } - Object maybeArray = evaluator.evaluate(arguments.get(0), data, jsonPath + "[0]"); + Object maybeArray; + + try { + maybeArray = evaluator.evaluate(arguments.get(0), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } // Array objects can have null values according to http://jsonlogic.com/ if (maybeArray == null) { @@ -41,13 +48,18 @@ public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, O } if (!ArrayLike.isEligible(maybeArray)) { - throw new JsonLogicEvaluationException("first argument to " + key() + " must be a valid array", jsonPath + "[0]"); + throw new JsonLogicEvaluationException("first argument to " + key() + " must be a valid array", "[0]"); } for (Object item : new ArrayLike(maybeArray)) { - if(JsonLogic.truthy(evaluator.evaluate(arguments.get(1), item, jsonPath + "[1]"))) { - return isSome; - } + try { + if (JsonLogic.truthy(evaluator.evaluate(arguments.get(1), item, ""))) { + return isSome; + } + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[1]"); + throw e; + } } return !isSome; diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/FilterExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/FilterExpression.java index 79364e9..11fce33 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/FilterExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/FilterExpression.java @@ -1,16 +1,16 @@ package io.github.jamsesso.jsonlogic.evaluator.expressions; -import io.github.jamsesso.jsonlogic.utils.ArrayLike; import io.github.jamsesso.jsonlogic.JsonLogic; import io.github.jamsesso.jsonlogic.ast.JsonLogicArray; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluationException; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluator; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicExpression; +import io.github.jamsesso.jsonlogic.utils.ArrayLike; import java.util.ArrayList; import java.util.List; -public class FilterExpression implements JsonLogicExpression { +public class FilterExpression extends JsonPathHandlerJsonLogicExpression implements JsonLogicExpression { public static final FilterExpression INSTANCE = new FilterExpression(); private FilterExpression() { @@ -23,24 +23,35 @@ public String key() { } @Override - public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data, String jsonPath) + public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) throws JsonLogicEvaluationException { if (arguments.size() != 2) { - throw new JsonLogicEvaluationException("filter expects exactly 2 arguments", jsonPath); + throw new JsonLogicEvaluationException("filter expects exactly 2 arguments"); } - Object maybeArray = evaluator.evaluate(arguments.get(0), data, jsonPath + "[0]"); + Object maybeArray; + try { + maybeArray = evaluator.evaluate(arguments.get(0), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } if (!ArrayLike.isEligible(maybeArray)) { - throw new JsonLogicEvaluationException("first argument to filter must be a valid array", jsonPath + "[0]"); + throw new JsonLogicEvaluationException("first argument to filter must be a valid array", "[0]"); } List result = new ArrayList<>(); for (Object item : new ArrayLike(maybeArray)) { - if(JsonLogic.truthy(evaluator.evaluate(arguments.get(1), item, jsonPath + "[1]"))) { - result.add(item); - } + try { + if (JsonLogic.truthy(evaluator.evaluate(arguments.get(1), item, ""))) { + result.add(item); + } + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[1]"); + throw e; + } } return result; diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/IfExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/IfExpression.java index 230a636..627f782 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/IfExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/IfExpression.java @@ -1,13 +1,13 @@ package io.github.jamsesso.jsonlogic.evaluator.expressions; -import io.github.jamsesso.jsonlogic.evaluator.JsonLogicExpression; import io.github.jamsesso.jsonlogic.JsonLogic; import io.github.jamsesso.jsonlogic.ast.JsonLogicArray; import io.github.jamsesso.jsonlogic.ast.JsonLogicNode; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluationException; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluator; +import io.github.jamsesso.jsonlogic.evaluator.JsonLogicExpression; -public class IfExpression implements JsonLogicExpression { +public class IfExpression extends JsonPathHandlerJsonLogicExpression implements JsonLogicExpression { public static final IfExpression IF = new IfExpression("if"); public static final IfExpression TERNARY = new IfExpression("?:"); @@ -23,8 +23,7 @@ public String key() { } @Override - public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data, - String jsonPath) + public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) throws JsonLogicEvaluationException { if (arguments.size() < 1) { return null; @@ -32,29 +31,64 @@ public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, O // If there is only a single argument, simply evaluate & return that argument. if (arguments.size() == 1) { - return evaluator.evaluate(arguments.get(0), data, jsonPath + "[0]"); + try { + return evaluator.evaluate(arguments.get(0), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } } // If there is 2 arguments, only evaluate the second argument if the first argument is truthy. if (arguments.size() == 2) { - return JsonLogic.truthy(evaluator.evaluate(arguments.get(0), data, jsonPath + "[0]")) - ? evaluator.evaluate(arguments.get(1), data, jsonPath + "[1]") - : null; + try { + if (!JsonLogic.truthy(evaluator.evaluate(arguments.get(0), data, ""))) { + return null; + } + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } + + try { + return evaluator.evaluate(arguments.get(1), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[1]"); + throw e; + } } for (int i = 0; i < arguments.size() - 1; i += 2) { JsonLogicNode condition = arguments.get(i); JsonLogicNode resultIfTrue = arguments.get(i + 1); - if (JsonLogic.truthy(evaluator.evaluate(condition, data, String.format("%s[%d]", jsonPath, i)))) { - return evaluator.evaluate(resultIfTrue, data, String.format("%s[%d]", jsonPath, i + 1)); + try { + if (!JsonLogic.truthy(evaluator.evaluate(condition, data, ""))) { + continue; + } + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[" + i + "]"); + throw e; } + + try { + return evaluator.evaluate(resultIfTrue, data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[" + (i + 1) + "]"); + throw e; + } + } if ((arguments.size() & 1) == 0) { return null; } - return evaluator.evaluate(arguments.get(arguments.size() - 1), data, String.format("%s[%d]", jsonPath, arguments.size() - 1)); + try { + return evaluator.evaluate(arguments.get(arguments.size() - 1), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[" + (arguments.size() - 1) + "]"); + throw e; + } } } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/InequalityExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/InequalityExpression.java index 747afb0..0cda458 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/InequalityExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/InequalityExpression.java @@ -5,7 +5,7 @@ import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluator; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicExpression; -public class InequalityExpression implements JsonLogicExpression { +public class InequalityExpression extends JsonPathHandlerJsonLogicExpression implements JsonLogicExpression { public static final InequalityExpression INSTANCE = new InequalityExpression(EqualityExpression.INSTANCE); private final EqualityExpression delegate; @@ -20,9 +20,9 @@ public String key() { } @Override - public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data, String jsonPath) + public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) throws JsonLogicEvaluationException { - boolean result = (boolean) delegate.evaluate(evaluator, arguments, data, jsonPath); + boolean result = (boolean) delegate.evaluate(evaluator, arguments, data, ""); return !result; } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/JsonPathHandlerJsonLogicExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/JsonPathHandlerJsonLogicExpression.java new file mode 100644 index 0000000..1b33efc --- /dev/null +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/JsonPathHandlerJsonLogicExpression.java @@ -0,0 +1,20 @@ +package io.github.jamsesso.jsonlogic.evaluator.expressions; + +import io.github.jamsesso.jsonlogic.ast.JsonLogicArray; +import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluationException; +import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluator; +import io.github.jamsesso.jsonlogic.evaluator.JsonLogicExpression; + +public abstract class JsonPathHandlerJsonLogicExpression implements JsonLogicExpression { + @Override + public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data, String jsonPath) throws JsonLogicEvaluationException { + try { + return evaluate(evaluator, arguments, data); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath(jsonPath); + throw e; + } + } + + public abstract Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) throws JsonLogicEvaluationException; +} diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/LogicExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/LogicExpression.java index 8412168..849a97e 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/LogicExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/LogicExpression.java @@ -7,7 +7,7 @@ import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluator; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicExpression; -public class LogicExpression implements JsonLogicExpression { +public class LogicExpression extends JsonPathHandlerJsonLogicExpression implements JsonLogicExpression { public static final LogicExpression AND = new LogicExpression(true); public static final LogicExpression OR = new LogicExpression(false); @@ -23,19 +23,25 @@ public String key() { } @Override - public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data, String jsonPath) + public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) throws JsonLogicEvaluationException { if (arguments.size() < 1) { - throw new JsonLogicEvaluationException(key() + " operator expects at least 1 argument", jsonPath); + throw new JsonLogicEvaluationException(key() + " operator expects at least 1 argument"); } Object result = null; - int index = 0; - for (JsonLogicNode element : arguments) { - result = evaluator.evaluate(element, data, String.format("%s[%d]", jsonPath, index++)); + for (int index = 0; index < arguments.size() ; index++) { + JsonLogicNode element = arguments.get(index); - if ((isAnd && !JsonLogic.truthy(result)) || (!isAnd && JsonLogic.truthy(result))) { + try { + result = evaluator.evaluate(element, data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[" + (index) + "]"); + throw e; + } + + if ((isAnd && !JsonLogic.truthy(result)) || (!isAnd && JsonLogic.truthy(result))) { return result; } } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/MapExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/MapExpression.java index 9c3a863..d273cbc 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/MapExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/MapExpression.java @@ -10,7 +10,7 @@ import java.util.Collections; import java.util.List; -public class MapExpression implements JsonLogicExpression { +public class MapExpression extends JsonPathHandlerJsonLogicExpression implements JsonLogicExpression { public static final MapExpression INSTANCE = new MapExpression(); private MapExpression() { @@ -23,22 +23,34 @@ public String key() { } @Override - public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data, String jsonPath) + public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) throws JsonLogicEvaluationException { if (arguments.size() != 2) { - throw new JsonLogicEvaluationException("map expects exactly 2 arguments", jsonPath); + throw new JsonLogicEvaluationException("map expects exactly 2 arguments"); } - Object maybeArray = evaluator.evaluate(arguments.get(0), data, jsonPath + "[0]"); + Object maybeArray; - if (!ArrayLike.isEligible(maybeArray)) { + try { + maybeArray = evaluator.evaluate(arguments.get(0), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } + + if (!ArrayLike.isEligible(maybeArray)) { return Collections.emptyList(); } List result = new ArrayList<>(); for (Object item : new ArrayLike(maybeArray)) { - result.add(evaluator.evaluate(arguments.get(1), item, jsonPath + "[1]")); + try { + result.add(evaluator.evaluate(arguments.get(1), item, "")); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[1]"); + throw e; + } } return result; diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ReduceExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ReduceExpression.java index 35bb882..6ae0fe7 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ReduceExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ReduceExpression.java @@ -1,15 +1,15 @@ package io.github.jamsesso.jsonlogic.evaluator.expressions; -import io.github.jamsesso.jsonlogic.utils.ArrayLike; import io.github.jamsesso.jsonlogic.ast.JsonLogicArray; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluationException; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluator; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicExpression; +import io.github.jamsesso.jsonlogic.utils.ArrayLike; import java.util.HashMap; import java.util.Map; -public class ReduceExpression implements JsonLogicExpression { +public class ReduceExpression extends JsonPathHandlerJsonLogicExpression implements JsonLogicExpression { public static final ReduceExpression INSTANCE = new ReduceExpression(); private ReduceExpression() { @@ -22,16 +22,30 @@ public String key() { } @Override - public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data, String jsonPath) + public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) throws JsonLogicEvaluationException { if (arguments.size() != 3) { - throw new JsonLogicEvaluationException("reduce expects exactly 3 arguments", jsonPath); + throw new JsonLogicEvaluationException("reduce expects exactly 3 arguments"); } - Object maybeArray = evaluator.evaluate(arguments.get(0), data, jsonPath + "[0]"); - Object accumulator = evaluator.evaluate(arguments.get(2), data, jsonPath + "[2]"); + Object maybeArray; + Object accumulator; + + try { + maybeArray = evaluator.evaluate(arguments.get(0), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } + + try { + accumulator = evaluator.evaluate(arguments.get(2), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[2]"); + throw e; + } - if (!ArrayLike.isEligible(maybeArray)) { + if (!ArrayLike.isEligible(maybeArray)) { return accumulator; } @@ -40,7 +54,12 @@ public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, O for (Object item : new ArrayLike(maybeArray)) { context.put("current", item); - context.put("accumulator", evaluator.evaluate(arguments.get(1), context, jsonPath + "[1]")); + try { + context.put("accumulator", evaluator.evaluate(arguments.get(1), context, "")); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[1]"); + throw e; + } } return context.get("accumulator"); From 7c2e7ace5274e2b449068eefcf97105cc3cc60c0 Mon Sep 17 00:00:00 2001 From: Guido Breitenhuber Date: Fri, 21 Nov 2025 19:52:51 +0100 Subject: [PATCH 2/2] Fix formatting --- .../github/jamsesso/jsonlogic/JsonLogic.java | 83 ++++---- .../jsonlogic/JsonLogicException.java | 42 ++-- .../ast/JsonLogicParseException.java | 6 +- .../jsonlogic/ast/JsonLogicParser.java | 48 ++--- .../JsonLogicEvaluationException.java | 19 +- .../evaluator/JsonLogicEvaluator.java | 201 +++++++++--------- .../evaluator/expressions/AllExpression.java | 2 +- .../expressions/ArrayHasExpression.java | 30 +-- .../expressions/FilterExpression.java | 30 +-- .../evaluator/expressions/IfExpression.java | 78 +++---- .../JsonPathHandlerJsonLogicExpression.java | 18 +- .../expressions/LogicExpression.java | 20 +- .../evaluator/expressions/MapExpression.java | 30 +-- .../expressions/ReduceExpression.java | 44 ++-- 14 files changed, 325 insertions(+), 326 deletions(-) diff --git a/src/main/java/io/github/jamsesso/jsonlogic/JsonLogic.java b/src/main/java/io/github/jamsesso/jsonlogic/JsonLogic.java index 3cf2351..ccf14f4 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/JsonLogic.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/JsonLogic.java @@ -2,7 +2,6 @@ import io.github.jamsesso.jsonlogic.ast.JsonLogicNode; import io.github.jamsesso.jsonlogic.ast.JsonLogicParser; -import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluationException; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluator; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicExpression; import io.github.jamsesso.jsonlogic.evaluator.expressions.*; @@ -55,44 +54,6 @@ public JsonLogic() { addOperation(MissingExpression.SOME); } - public JsonLogic addOperation(String name, Function function) { - return addOperation(new PreEvaluatedArgumentsExpression() { - @Override - public Object evaluate(List arguments, Object data, String jsonPath) { - return function.apply(arguments.toArray()); - } - - @Override - public String key() { - return name; - } - }); - } - - public JsonLogic addOperation(JsonLogicExpression expression) { - expressions.put(expression.key(), expression); - evaluator = null; - - return this; - } - - public Object apply(String json, Object data) throws JsonLogicException { - if (!parseCache.containsKey(json)) { - parseCache.put(json, JsonLogicParser.parse(json)); - } - - if (evaluator == null) { - evaluator = new JsonLogicEvaluator(expressions); - } - - try { - return evaluator.evaluate(parseCache.get(json), data, ""); - } catch (JsonLogicException e) { - e.prependPartialJsonPath("$"); - throw e; - } - } - public static boolean truthy(Object value) { if (value == null) { return false; @@ -108,8 +69,7 @@ public static boolean truthy(Object value) { if (d.isNaN()) { return false; - } - else if (d.isInfinite()) { + } else if (d.isInfinite()) { return true; } } @@ -119,8 +79,7 @@ else if (d.isInfinite()) { if (f.isNaN()) { return false; - } - else if (f.isInfinite()) { + } else if (f.isInfinite()) { return true; } } @@ -142,4 +101,42 @@ else if (f.isInfinite()) { return true; } + + public JsonLogic addOperation(String name, Function function) { + return addOperation(new PreEvaluatedArgumentsExpression() { + @Override + public Object evaluate(List arguments, Object data, String jsonPath) { + return function.apply(arguments.toArray()); + } + + @Override + public String key() { + return name; + } + }); + } + + public JsonLogic addOperation(JsonLogicExpression expression) { + expressions.put(expression.key(), expression); + evaluator = null; + + return this; + } + + public Object apply(String json, Object data) throws JsonLogicException { + if (!parseCache.containsKey(json)) { + parseCache.put(json, JsonLogicParser.parse(json)); + } + + if (evaluator == null) { + evaluator = new JsonLogicEvaluator(expressions); + } + + try { + return evaluator.evaluate(parseCache.get(json), data, ""); + } catch (JsonLogicException e) { + e.prependPartialJsonPath("$"); + throw e; + } + } } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/JsonLogicException.java b/src/main/java/io/github/jamsesso/jsonlogic/JsonLogicException.java index ee654b2..7db44a5 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/JsonLogicException.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/JsonLogicException.java @@ -2,47 +2,47 @@ public class JsonLogicException extends Exception { - private final StringBuilder jsonPath = new StringBuilder(); + private final StringBuilder jsonPath = new StringBuilder(); private JsonLogicException() { // The default constructor should not be called for exceptions. A reason must be provided. } - public JsonLogicException(String msg) { - super(msg); - } + public JsonLogicException(String msg) { + super(msg); + } public JsonLogicException(String msg, String jsonPath) { - super(msg); - prependPartialJsonPath(jsonPath); + super(msg); + prependPartialJsonPath(jsonPath); } - public JsonLogicException(Throwable cause) { - super(cause); - } + public JsonLogicException(Throwable cause) { + super(cause); + } public JsonLogicException(Throwable cause, String jsonPath) { - super(cause); - prependPartialJsonPath(jsonPath); + super(cause); + prependPartialJsonPath(jsonPath); } - public JsonLogicException(String msg, Throwable cause) { - super(msg, cause); - } + public JsonLogicException(String msg, Throwable cause) { + super(msg, cause); + } public JsonLogicException(String msg, Throwable cause, String jsonPath) { super(msg, cause); prependPartialJsonPath(jsonPath); } - public String getJsonPath() { - return jsonPath.toString(); + public String getJsonPath() { + return jsonPath.toString(); } - public void prependPartialJsonPath(String partialPath) { - if (partialPath == null) { - return; - } - jsonPath.insert(0, partialPath); + public void prependPartialJsonPath(String partialPath) { + if (partialPath == null) { + return; } + jsonPath.insert(0, partialPath); + } } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParseException.java b/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParseException.java index 88547da..8d56eae 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParseException.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParseException.java @@ -15,7 +15,7 @@ public JsonLogicParseException(String msg, Throwable cause, String jsonPath) { super(msg, cause, jsonPath); } - public JsonLogicParseException(String msg) { - super(msg); - } + public JsonLogicParseException(String msg) { + super(msg); + } } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParser.java b/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParser.java index 66f7856..2d8bbf8 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParser.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/ast/JsonLogicParser.java @@ -16,12 +16,10 @@ private JsonLogicParser() { public static JsonLogicNode parse(String json) throws JsonLogicParseException { try { return parse(PARSER.parse(json)); - } - catch (JsonLogicParseException e) { - e.prependPartialJsonPath("$"); - throw e; - } - catch (JsonSyntaxException e) { + } catch (JsonLogicParseException e) { + e.prependPartialJsonPath("$"); + throw e; + } catch (JsonSyntaxException e) { throw new JsonLogicParseException(e, "$"); } } @@ -46,8 +44,7 @@ private static JsonLogicNode parse(JsonElement root) throws JsonLogicParseExcept if (primitive.isBoolean() && primitive.getAsBoolean()) { return JsonLogicBoolean.TRUE; - } - else { + } else { return JsonLogicBoolean.FALSE; } } @@ -58,15 +55,15 @@ private static JsonLogicNode parse(JsonElement root) throws JsonLogicParseExcept List elements = new ArrayList<>(array.size()); for (int index = 0; index < array.size(); index++) { - JsonElement element = array.get(index); - JsonLogicNode arrayNode; - try { - arrayNode = parse(element); - } catch (JsonLogicParseException e) { - e.prependPartialJsonPath("[" + (index) + "]"); - throw e; - } - elements.add(arrayNode); + JsonElement element = array.get(index); + JsonLogicNode arrayNode; + try { + arrayNode = parse(element); + } catch (JsonLogicParseException e) { + e.prependPartialJsonPath("[" + (index) + "]"); + throw e; + } + elements.add(arrayNode); } return new JsonLogicArray(elements); @@ -83,18 +80,17 @@ private static JsonLogicNode parse(JsonElement root) throws JsonLogicParseExcept JsonLogicNode argumentNode; JsonLogicArray arguments; - try { - argumentNode = parse(object.get(key)); - } catch (JsonLogicParseException e) { - e.prependPartialJsonPath("." + key); - throw e; - } + try { + argumentNode = parse(object.get(key)); + } catch (JsonLogicParseException e) { + e.prependPartialJsonPath("." + key); + throw e; + } - // Always coerce single-argument operations into a JsonLogicArray with a single element. + // Always coerce single-argument operations into a JsonLogicArray with a single element. if (argumentNode instanceof JsonLogicArray) { arguments = (JsonLogicArray) argumentNode; - } - else { + } else { arguments = new JsonLogicArray(Collections.singletonList(argumentNode)); } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluationException.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluationException.java index 8f5723f..c7ac54c 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluationException.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluationException.java @@ -3,24 +3,25 @@ import io.github.jamsesso.jsonlogic.JsonLogicException; public class JsonLogicEvaluationException extends JsonLogicException { - public JsonLogicEvaluationException(String msg) { - super(msg); - } + public JsonLogicEvaluationException(String msg) { + super(msg); + } + public JsonLogicEvaluationException(String msg, String jsonPath) { super(msg, jsonPath); } - public JsonLogicEvaluationException(Throwable cause) { - super(cause); - } + public JsonLogicEvaluationException(Throwable cause) { + super(cause); + } public JsonLogicEvaluationException(Throwable cause, String jsonPath) { super(cause, jsonPath); } - public JsonLogicEvaluationException(String msg, Throwable cause) { - super(msg, cause); - } + public JsonLogicEvaluationException(String msg, Throwable cause) { + super(msg, cause); + } public JsonLogicEvaluationException(String msg, Throwable cause, String jsonPath) { super(msg, cause, jsonPath); diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluator.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluator.java index 722bd24..3db67d4 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluator.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/JsonLogicEvaluator.java @@ -8,7 +8,9 @@ public class JsonLogicEvaluator { - /** Sentinel object to represent a missing value (for internal use only). */ + /** + * Sentinel object to represent a missing value (for internal use only). + */ private static final Object MISSING = new Object(); private final Map expressions; @@ -25,34 +27,46 @@ public JsonLogicEvaluator(Map expressions) { this.expressions = Collections.unmodifiableMap(expressions); } + public static Object transform(Object value) { + if (value instanceof Number) { + return ((Number) value).doubleValue(); + } + + return value; + } + @Deprecated public Object evaluate(JsonLogicNode node, Object data, String jsonPath) throws JsonLogicEvaluationException { - try { - return evaluate(node, data); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath(jsonPath); - throw e; - } + try { + return evaluate(node, data); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath(jsonPath); + throw e; + } } - public Object evaluate(JsonLogicNode node, Object data) throws JsonLogicEvaluationException { - switch (node.getType()) { - case PRIMITIVE: return evaluate((JsonLogicPrimitive) node); - case VARIABLE: - try { - return evaluate((JsonLogicVariable) node, data); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath(".var"); - throw e; - } - case ARRAY: return evaluate((JsonLogicArray) node, data); - default: return evaluate((JsonLogicOperation) node, data); + public Object evaluate(JsonLogicNode node, Object data) throws JsonLogicEvaluationException { + switch (node.getType()) { + case PRIMITIVE: + return evaluate((JsonLogicPrimitive) node); + case VARIABLE: + try { + return evaluate((JsonLogicVariable) node, data); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath(".var"); + throw e; } + case ARRAY: + return evaluate((JsonLogicArray) node, data); + default: + return evaluate((JsonLogicOperation) node, data); } + } public Object evaluate(JsonLogicPrimitive primitive) { switch (primitive.getPrimitiveType()) { - case NUMBER: return ((JsonLogicNumber) primitive).getValue(); + case NUMBER: + return ((JsonLogicNumber) primitive).getValue(); default: return primitive.getValue(); @@ -60,52 +74,52 @@ public Object evaluate(JsonLogicPrimitive primitive) { } @Deprecated - public Object evaluate(JsonLogicVariable variable, Object data, String jsonPath) - throws JsonLogicEvaluationException { - try { - return evaluate(variable, data); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath(jsonPath); - throw e; - } + public Object evaluate(JsonLogicVariable variable, Object data, String jsonPath) + throws JsonLogicEvaluationException { + try { + return evaluate(variable, data); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath(jsonPath); + throw e; } + } public Object evaluate(JsonLogicVariable variable, Object data) throws JsonLogicEvaluationException { - Object defaultValue; + Object defaultValue; - try { - defaultValue = evaluate(variable.getDefaultValue(), null, ""); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[1]"); - throw e; - } + try { + defaultValue = evaluate(variable.getDefaultValue(), null, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[1]"); + throw e; + } - if (data == null) { + if (data == null) { return defaultValue; } - Object key; + Object key; + + try { + key = evaluate(variable.getKey(), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } + if (key == null) { + Object varValue; try { - key = evaluate(variable.getKey(), data, ""); + varValue = evaluate(variable.getDefaultValue(), null, ""); } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[0]"); - throw e; + e.prependPartialJsonPath("[0]"); + throw e; } - if (key == null) { - Object varValue; - try { - varValue = evaluate(variable.getDefaultValue(), null, ""); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[0]"); - throw e; - } - - return Optional.of(data) - .map(JsonLogicEvaluator::transform) - .orElse(varValue); + return Optional.of(data) + .map(JsonLogicEvaluator::transform) + .orElse(varValue); } if (key instanceof Number) { @@ -134,14 +148,14 @@ public Object evaluate(JsonLogicVariable variable, Object data) Object result = data; for (String partial : keys) { - try { - result = evaluatePartialVariable(partial, result); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[0]"); - throw e; - } - - if (result == MISSING) { + try { + result = evaluatePartialVariable(partial, result); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } + + if (result == MISSING) { return defaultValue; } else if (result == null) { return null; @@ -154,16 +168,15 @@ public Object evaluate(JsonLogicVariable variable, Object data) throw new JsonLogicEvaluationException("var first argument must be null, number, or string", "[0]"); } - private Object evaluatePartialVariable(String key, Object data) throws JsonLogicEvaluationException { + private Object evaluatePartialVariable(String key, Object data) throws JsonLogicEvaluationException { if (ArrayLike.isEligible(data)) { ArrayLike list = new ArrayLike(data); int index; try { index = Integer.parseInt(key); - } - catch (NumberFormatException e) { - throw new JsonLogicEvaluationException(e); + } catch (NumberFormatException e) { + throw new JsonLogicEvaluationException(e); } if (index < 0 || index >= list.size()) { @@ -186,26 +199,26 @@ private Object evaluatePartialVariable(String key, Object data) throws JsonLogic } @Deprecated - public List evaluate(JsonLogicArray array, Object data, String jsonPath) throws JsonLogicEvaluationException { - try { - return evaluate(array, data); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath(jsonPath); - throw e; - } + public List evaluate(JsonLogicArray array, Object data, String jsonPath) throws JsonLogicEvaluationException { + try { + return evaluate(array, data); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath(jsonPath); + throw e; } + } public List evaluate(JsonLogicArray array, Object data) throws JsonLogicEvaluationException { List values = new ArrayList<>(array.size()); - for(int index = 0; index < array.size(); index++) { - JsonLogicNode element = array.get(index); - try { - values.add(evaluate(element, data, "")); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[" + index + "]"); - throw e; - } + for (int index = 0; index < array.size(); index++) { + JsonLogicNode element = array.get(index); + try { + values.add(evaluate(element, data, "")); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[" + index + "]"); + throw e; + } } return values; @@ -213,12 +226,12 @@ public List evaluate(JsonLogicArray array, Object data) throws JsonLogic @Deprecated public Object evaluate(JsonLogicOperation operation, Object data, String jsonPath) throws JsonLogicEvaluationException { - try { - return evaluate(operation, data); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath(jsonPath); - throw e; - } + try { + return evaluate(operation, data); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath(jsonPath); + throw e; + } } public Object evaluate(JsonLogicOperation operation, Object data) throws JsonLogicEvaluationException { @@ -228,19 +241,11 @@ public Object evaluate(JsonLogicOperation operation, Object data) throws JsonLog throw new JsonLogicEvaluationException("Undefined operation '" + operation.getOperator() + "'"); } - try { - return handler.evaluate(this, operation.getArguments(), data, ""); - } catch (JsonLogicException e) { - e.prependPartialJsonPath("." + operation.getOperator()); - throw e; - } - } - - public static Object transform(Object value) { - if (value instanceof Number) { - return ((Number) value).doubleValue(); + try { + return handler.evaluate(this, operation.getArguments(), data, ""); + } catch (JsonLogicException e) { + e.prependPartialJsonPath("." + operation.getOperator()); + throw e; } - - return value; } } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/AllExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/AllExpression.java index 04d9900..5ba78bf 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/AllExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/AllExpression.java @@ -21,7 +21,7 @@ public String key() { @Override public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) - throws JsonLogicEvaluationException { + throws JsonLogicEvaluationException { if (arguments.size() != 2) { throw new JsonLogicEvaluationException("all expects exactly 2 arguments"); } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ArrayHasExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ArrayHasExpression.java index 8504e9f..00d209d 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ArrayHasExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ArrayHasExpression.java @@ -24,19 +24,19 @@ public String key() { @Override public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) - throws JsonLogicEvaluationException { + throws JsonLogicEvaluationException { if (arguments.size() != 2) { throw new JsonLogicEvaluationException(key() + " expects exactly 2 arguments"); } - Object maybeArray; + Object maybeArray; - try { - maybeArray = evaluator.evaluate(arguments.get(0), data, ""); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[0]"); - throw e; - } + try { + maybeArray = evaluator.evaluate(arguments.get(0), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } // Array objects can have null values according to http://jsonlogic.com/ if (maybeArray == null) { @@ -52,14 +52,14 @@ public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, O } for (Object item : new ArrayLike(maybeArray)) { - try { - if (JsonLogic.truthy(evaluator.evaluate(arguments.get(1), item, ""))) { - return isSome; - } - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[1]"); - throw e; + try { + if (JsonLogic.truthy(evaluator.evaluate(arguments.get(1), item, ""))) { + return isSome; } + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[1]"); + throw e; + } } return !isSome; diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/FilterExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/FilterExpression.java index 11fce33..ab7752b 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/FilterExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/FilterExpression.java @@ -24,18 +24,18 @@ public String key() { @Override public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) - throws JsonLogicEvaluationException { + throws JsonLogicEvaluationException { if (arguments.size() != 2) { throw new JsonLogicEvaluationException("filter expects exactly 2 arguments"); } - Object maybeArray; - try { - maybeArray = evaluator.evaluate(arguments.get(0), data, ""); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[0]"); - throw e; - } + Object maybeArray; + try { + maybeArray = evaluator.evaluate(arguments.get(0), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } if (!ArrayLike.isEligible(maybeArray)) { throw new JsonLogicEvaluationException("first argument to filter must be a valid array", "[0]"); @@ -44,14 +44,14 @@ public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, O List result = new ArrayList<>(); for (Object item : new ArrayLike(maybeArray)) { - try { - if (JsonLogic.truthy(evaluator.evaluate(arguments.get(1), item, ""))) { - result.add(item); - } - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[1]"); - throw e; + try { + if (JsonLogic.truthy(evaluator.evaluate(arguments.get(1), item, ""))) { + result.add(item); } + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[1]"); + throw e; + } } return result; diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/IfExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/IfExpression.java index 627f782..7c4ccc1 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/IfExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/IfExpression.java @@ -24,59 +24,59 @@ public String key() { @Override public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) - throws JsonLogicEvaluationException { + throws JsonLogicEvaluationException { if (arguments.size() < 1) { return null; } // If there is only a single argument, simply evaluate & return that argument. if (arguments.size() == 1) { - try { - return evaluator.evaluate(arguments.get(0), data, ""); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[0]"); - throw e; - } + try { + return evaluator.evaluate(arguments.get(0), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } } // If there is 2 arguments, only evaluate the second argument if the first argument is truthy. if (arguments.size() == 2) { - try { - if (!JsonLogic.truthy(evaluator.evaluate(arguments.get(0), data, ""))) { - return null; - } - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[0]"); - throw e; + try { + if (!JsonLogic.truthy(evaluator.evaluate(arguments.get(0), data, ""))) { + return null; } + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } - try { - return evaluator.evaluate(arguments.get(1), data, ""); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[1]"); - throw e; - } + try { + return evaluator.evaluate(arguments.get(1), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[1]"); + throw e; + } } for (int i = 0; i < arguments.size() - 1; i += 2) { JsonLogicNode condition = arguments.get(i); JsonLogicNode resultIfTrue = arguments.get(i + 1); - try { - if (!JsonLogic.truthy(evaluator.evaluate(condition, data, ""))) { - continue; - } - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[" + i + "]"); - throw e; + try { + if (!JsonLogic.truthy(evaluator.evaluate(condition, data, ""))) { + continue; + } + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[" + i + "]"); + throw e; } - try { - return evaluator.evaluate(resultIfTrue, data, ""); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[" + (i + 1) + "]"); - throw e; - } + try { + return evaluator.evaluate(resultIfTrue, data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[" + (i + 1) + "]"); + throw e; + } } @@ -84,11 +84,11 @@ public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, O return null; } - try { - return evaluator.evaluate(arguments.get(arguments.size() - 1), data, ""); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[" + (arguments.size() - 1) + "]"); - throw e; - } + try { + return evaluator.evaluate(arguments.get(arguments.size() - 1), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[" + (arguments.size() - 1) + "]"); + throw e; + } } } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/JsonPathHandlerJsonLogicExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/JsonPathHandlerJsonLogicExpression.java index 1b33efc..8cb3c56 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/JsonPathHandlerJsonLogicExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/JsonPathHandlerJsonLogicExpression.java @@ -6,15 +6,15 @@ import io.github.jamsesso.jsonlogic.evaluator.JsonLogicExpression; public abstract class JsonPathHandlerJsonLogicExpression implements JsonLogicExpression { - @Override - public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data, String jsonPath) throws JsonLogicEvaluationException { - try { - return evaluate(evaluator, arguments, data); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath(jsonPath); - throw e; - } + @Override + public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data, String jsonPath) throws JsonLogicEvaluationException { + try { + return evaluate(evaluator, arguments, data); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath(jsonPath); + throw e; } + } - public abstract Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) throws JsonLogicEvaluationException; + public abstract Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) throws JsonLogicEvaluationException; } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/LogicExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/LogicExpression.java index 849a97e..f875e8a 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/LogicExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/LogicExpression.java @@ -24,24 +24,24 @@ public String key() { @Override public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) - throws JsonLogicEvaluationException { + throws JsonLogicEvaluationException { if (arguments.size() < 1) { throw new JsonLogicEvaluationException(key() + " operator expects at least 1 argument"); } Object result = null; - for (int index = 0; index < arguments.size() ; index++) { - JsonLogicNode element = arguments.get(index); + for (int index = 0; index < arguments.size(); index++) { + JsonLogicNode element = arguments.get(index); - try { - result = evaluator.evaluate(element, data, ""); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[" + (index) + "]"); - throw e; - } + try { + result = evaluator.evaluate(element, data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[" + (index) + "]"); + throw e; + } - if ((isAnd && !JsonLogic.truthy(result)) || (!isAnd && JsonLogic.truthy(result))) { + if ((isAnd && !JsonLogic.truthy(result)) || (!isAnd && JsonLogic.truthy(result))) { return result; } } diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/MapExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/MapExpression.java index d273cbc..e82dbab 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/MapExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/MapExpression.java @@ -24,33 +24,33 @@ public String key() { @Override public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) - throws JsonLogicEvaluationException { + throws JsonLogicEvaluationException { if (arguments.size() != 2) { throw new JsonLogicEvaluationException("map expects exactly 2 arguments"); } - Object maybeArray; + Object maybeArray; - try { - maybeArray = evaluator.evaluate(arguments.get(0), data, ""); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[0]"); - throw e; - } + try { + maybeArray = evaluator.evaluate(arguments.get(0), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } - if (!ArrayLike.isEligible(maybeArray)) { + if (!ArrayLike.isEligible(maybeArray)) { return Collections.emptyList(); } List result = new ArrayList<>(); for (Object item : new ArrayLike(maybeArray)) { - try { - result.add(evaluator.evaluate(arguments.get(1), item, "")); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[1]"); - throw e; - } + try { + result.add(evaluator.evaluate(arguments.get(1), item, "")); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[1]"); + throw e; + } } return result; diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ReduceExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ReduceExpression.java index 6ae0fe7..439c0f9 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ReduceExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ReduceExpression.java @@ -23,29 +23,29 @@ public String key() { @Override public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, Object data) - throws JsonLogicEvaluationException { + throws JsonLogicEvaluationException { if (arguments.size() != 3) { throw new JsonLogicEvaluationException("reduce expects exactly 3 arguments"); } - Object maybeArray; - Object accumulator; + Object maybeArray; + Object accumulator; - try { - maybeArray = evaluator.evaluate(arguments.get(0), data, ""); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[0]"); - throw e; - } + try { + maybeArray = evaluator.evaluate(arguments.get(0), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[0]"); + throw e; + } - try { - accumulator = evaluator.evaluate(arguments.get(2), data, ""); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[2]"); - throw e; - } + try { + accumulator = evaluator.evaluate(arguments.get(2), data, ""); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[2]"); + throw e; + } - if (!ArrayLike.isEligible(maybeArray)) { + if (!ArrayLike.isEligible(maybeArray)) { return accumulator; } @@ -54,12 +54,12 @@ public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, O for (Object item : new ArrayLike(maybeArray)) { context.put("current", item); - try { - context.put("accumulator", evaluator.evaluate(arguments.get(1), context, "")); - } catch (JsonLogicEvaluationException e) { - e.prependPartialJsonPath("[1]"); - throw e; - } + try { + context.put("accumulator", evaluator.evaluate(arguments.get(1), context, "")); + } catch (JsonLogicEvaluationException e) { + e.prependPartialJsonPath("[1]"); + throw e; + } } return context.get("accumulator");