Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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<Double, Double, Double> reducer;
private final BiFunction<BigDecimal, BigDecimal, BigDecimal> reducer;
private final int maxArguments;

public MathExpression(String key, BiFunction<Double, Double, Double> reducer) {
public MathExpression(String key, BiFunction<BigDecimal, BigDecimal, BigDecimal> reducer) {
this(key, reducer, 0);
}

public MathExpression(String key, BiFunction<Double, Double, Double> reducer, int maxArguments) {
public MathExpression(String key, BiFunction<BigDecimal, BigDecimal, BigDecimal> reducer, int maxArguments) {
this.key = key;
this.reducer = reducer;
this.maxArguments = maxArguments;
Expand All @@ -41,53 +44,54 @@ 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]);
}

return accumulator;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down