diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/MathExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/MathExpression.java index e1d656b..64bf03a 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/MathExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/MathExpression.java @@ -3,27 +3,30 @@ import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluationException; import io.github.jamsesso.jsonlogic.utils.ArrayLike; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.List; import java.util.function.BiFunction; public class MathExpression implements PreEvaluatedArgumentsExpression { - public static final MathExpression ADD = new MathExpression("+", Double::sum); - public static final MathExpression SUBTRACT = new MathExpression("-", (a, b) -> a - b, 2); - public static final MathExpression MULTIPLY = new MathExpression("*", (a, b) -> a * b); - public static final MathExpression DIVIDE = new MathExpression("/", (a, b) -> a / b, 2); - public static final MathExpression MODULO = new MathExpression("%", (a, b) -> a % b, 2); - public static final MathExpression MIN = new MathExpression("min", Math::min); - public static final MathExpression MAX = new MathExpression("max", Math::max); + public static final MathExpression ADD = new MathExpression("+", BigDecimal::add); + public static final MathExpression SUBTRACT = new MathExpression("-", BigDecimal::subtract, 2); + public static final MathExpression MULTIPLY = new MathExpression("*", BigDecimal::multiply); + public static final MathExpression DIVIDE = new MathExpression("/", + (a, b) -> a.divide(b, 10, RoundingMode.HALF_UP), 2); + public static final MathExpression MODULO = new MathExpression("%", BigDecimal::remainder, 2); + public static final MathExpression MIN = new MathExpression("min", BigDecimal::min); + public static final MathExpression MAX = new MathExpression("max", BigDecimal::max); private final String key; - private final BiFunction reducer; + private final BiFunction reducer; private final int maxArguments; - public MathExpression(String key, BiFunction reducer) { + public MathExpression(String key, BiFunction reducer) { this(key, reducer, 0); } - public MathExpression(String key, BiFunction reducer, int maxArguments) { + public MathExpression(String key, BiFunction reducer, int maxArguments) { this.key = key; this.reducer = reducer; this.maxArguments = maxArguments; @@ -41,48 +44,49 @@ public Object evaluate(List arguments, Object data, String jsonPath) throws Json } // Collect all of the arguments - double[] values = new double[arguments.size()]; + BigDecimal[] values = new BigDecimal[arguments.size()]; for (int i = 0; i < arguments.size(); i++) { Object value = arguments.get(i); + // 处理 null 和空字符串,默认为 0 + if (value == null || "".equals(value)) { + values[i] = BigDecimal.ZERO; + continue; + } + if (key.equals("*") || key.equals("+")) { while (ArrayLike.isEligible(value)) { - ArrayLike array = new ArrayLike(value); - if (array.isEmpty()) { - break; - } - value = array.get(0); + value = new ArrayLike(value).get(0); } } + if (value instanceof String) { try { - values[i] = Double.parseDouble((String) value); - } - catch (NumberFormatException e) { + values[i] = new BigDecimal((String) value); + } catch (NumberFormatException e) { return null; } - } - else if (!(value instanceof Number)) { + } else if (value instanceof BigDecimal) { + values[i] = (BigDecimal) value; + } else if (value instanceof Number) { + values[i] = new BigDecimal(value.toString()); + } else { return null; } - else { - values[i] = ((Number) value).doubleValue(); - } } if (values.length == 1) { if (key.equals("-")) { - return -values[0]; + return values[0].negate(); } - if (key.equals("/")) { return null; } } // Reduce the values into a single result - double accumulator = values[0]; + BigDecimal accumulator = values[0]; for (int i = 1; i < values.length && (i < maxArguments || maxArguments == 0); i++) { accumulator = reducer.apply(accumulator, values[i]); @@ -90,4 +94,4 @@ else if (!(value instanceof Number)) { return accumulator; } -} +} \ No newline at end of file diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/NumericComparisonExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/NumericComparisonExpression.java index 98c98a4..83bf63f 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/NumericComparisonExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/NumericComparisonExpression.java @@ -35,6 +35,12 @@ public Object evaluate(List arguments, Object data, String jsonPath) throws Json for (int i = 0; i < n; i++) { Object value = arguments.get(i); + // 处理 null 和空字符串,默认为 0 + if (value == null || "".equals(value)) { + values[i] = 0.0; + continue; + } + if (value instanceof String) { try { values[i] = Double.parseDouble((String) value);