Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiplication & Division functions #911

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
30 changes: 16 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,22 @@ Functions
Functions can be invoked at the tail end of a path - the input to a function is the output of the path expression.
The function output is dictated by the function itself.

| Function | Description | Output type |
|:----------|:-------------------------------------------------------------------------------------|:---------------------|
| min() | Provides the min value of an array of numbers | Double |
| max() | Provides the max value of an array of numbers | Double |
| avg() | Provides the average value of an array of numbers | Double |
| stddev() | Provides the standard deviation value of an array of numbers | Double |
| length() | Provides the length of an array | Integer |
| sum() | Provides the sum value of an array of numbers | Double |
| keys() | Provides the property keys (An alternative for terminal tilde `~`) | `Set<E>` |
| concat(X) | Provides a concatinated version of the path output with a new item | like input |
| append(X) | add an item to the json path output array | like input |
| first() | Provides the first item of an array | Depends on the array |
| last() | Provides the last item of an array | Depends on the array |
| index(X) | Provides the item of an array of index: X, if the X is negative, take from backwards | Depends on the array |
| Function | Description | Output type |
|:----------------------------|:-------------------------------------------------------------------------------------|:---------------------|
| min() | Provides the min value of an array of numbers | Double |
| max() | Provides the max value of an array of numbers | Double |
| avg() | Provides the average value of an array of numbers | Double |
| stddev() | Provides the standard deviation value of an array of numbers | Double |
| length() | Provides the length of an array | Integer |
| sum() | Provides the sum value of an array of numbers | Double |
| mul() | Provides the multiplication value of an array of numbers | Double |
| div(numerator, denominator) | Provides the division value of parameters | Double |
| keys() | Provides the property keys (An alternative for terminal tilde `~`) | `Set<E>` |
| concat(X) | Provides a concatinated version of the path output with a new item | like input |
| append(X) | add an item to the json path output array | like input |
| first() | Provides the first item of an array | Depends on the array |
| last() | Provides the last item of an array | Depends on the array |
| index(X) | Provides the item of an array of index: X, if the X is negative, take from backwards | Depends on the array |
Filter Operators
-----------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.internal.function.json.Append;
import com.jayway.jsonpath.internal.function.json.KeySetFunction;
import com.jayway.jsonpath.internal.function.numeric.Average;
import com.jayway.jsonpath.internal.function.numeric.Max;
import com.jayway.jsonpath.internal.function.numeric.Min;
import com.jayway.jsonpath.internal.function.numeric.StandardDeviation;
import com.jayway.jsonpath.internal.function.numeric.Sum;
import com.jayway.jsonpath.internal.function.numeric.*;
import com.jayway.jsonpath.internal.function.sequence.First;
import com.jayway.jsonpath.internal.function.sequence.Index;
import com.jayway.jsonpath.internal.function.sequence.Last;
Expand Down Expand Up @@ -40,6 +36,8 @@ public class PathFunctionFactory {
map.put("sum", Sum.class);
map.put("min", Min.class);
map.put("max", Max.class);
map.put("mul", Multiply.class);
map.put("div", Divide.class);

// Text Functions
map.put("concat", Concatenate.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.jayway.jsonpath.internal.function.numeric;

import com.jayway.jsonpath.JsonPathException;
import com.jayway.jsonpath.internal.EvaluationContext;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.internal.function.Parameter;
import com.jayway.jsonpath.internal.function.PathFunction;

import java.util.List;

public class Divide implements PathFunction {
@Override
public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {
if (parameters != null && parameters.size() == 2) {
List<Number> numbers = Parameter.toList(Number.class, ctx, parameters);
if (numbers.get(1).doubleValue() == 0d) {
throw new JsonPathException("Arithmetic error: Divide by zero");
}
return numbers.get(0).doubleValue()/numbers.get(1).doubleValue();
}
throw new JsonPathException("Exactly 2 parameters are expected for divide operator");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.jayway.jsonpath.internal.function.numeric;

public class Multiply extends AbstractAggregation {
private Double multiplication = 1d;

@Override
protected void next(Number value) {
multiplication *= value.doubleValue();
}

@Override
protected Number getValue() {
return multiplication;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,48 @@ public void testStdDevOfDouble() {
verifyMathFunction(conf, "$.numbers.stddev()", 2.8722813232690143d);
}

@Test
public void testMultiplication() {
verifyMathFunction(conf, "$.numbers.mul()", 3628800d);
}

@Test
public void testMultiplicationEmptyListNegative() {
try {
verifyMathFunction(conf, "$.empty.mul()", null);
} catch (JsonPathException e) {
assertEquals(e.getMessage(), "Aggregation function attempted to calculate value using empty array");
}
}

@Test
public void testMultiplicationParameter() {
verifyFunction(conf, "mul($.left, $.right)", "{\"left\": 3, \"right\": 4}",12d);
}

@Test
public void testDivideNoParamsNegative() {
try {
verifyMathFunction(conf, "$.numbers.div()", null);
} catch (JsonPathException e) {
assertEquals(e.getMessage(), "Exactly 2 parameters are expected for divide operator");
}
}

@Test
public void testDivide() {
verifyFunction(conf, "div($.num, $.den)", "{\"num\": 1, \"den\": 2}", 0.5d);
}

@Test
public void testDivideByZeroNegative() {
try {
verifyFunction(conf, "div($.num, $.den)", "{\"num\": 1, \"den\": 0}", 0.5d);
} catch (JsonPathException e){
assertEquals(e.getMessage(), "Arithmetic error: Divide by zero");
}
}

@Test
public void testStddevOfEmptyListNegative() {
try {
Expand Down