Skip to content

Commit e707a46

Browse files
Defines the pattern for taking unique items from collection of JSONArray
1 parent 21de620 commit e707a46

File tree

5 files changed

+99
-15
lines changed

5 files changed

+99
-15
lines changed

README.md

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,21 @@ Functions
8585
Functions can be invoked at the tail end of a path - the input to a function is the output of the path expression.
8686
The function output is dictated by the function itself.
8787

88-
| Function | Description | Output type |
89-
|:----------|:-------------------------------------------------------------------------------------|:---------------------|
90-
| min() | Provides the min value of an array of numbers | Double |
91-
| max() | Provides the max value of an array of numbers | Double |
92-
| avg() | Provides the average value of an array of numbers | Double |
93-
| stddev() | Provides the standard deviation value of an array of numbers | Double |
94-
| length() | Provides the length of an array | Integer |
95-
| sum() | Provides the sum value of an array of numbers | Double |
96-
| keys() | Provides the property keys (An alternative for terminal tilde `~`) | `Set<E>` |
97-
| concat(X) | Provides a concatinated version of the path output with a new item | like input |
98-
| append(X) | add an item to the json path output array | like input |
99-
| first() | Provides the first item of an array | Depends on the array |
100-
| last() | Provides the last item of an array | Depends on the array |
101-
| index(X) | Provides the item of an array of index: X, if the X is negative, take from backwards | Depends on the array |
88+
| Function | Description | Output type |
89+
|:-----------|:-------------------------------------------------------------------------------------|:---------------------|
90+
| min() | Provides the min value of an array of numbers | Double |
91+
| max() | Provides the max value of an array of numbers | Double |
92+
| avg() | Provides the average value of an array of numbers | Double |
93+
| stddev() | Provides the standard deviation value of an array of numbers | Double |
94+
| length() | Provides the length of an array | Integer |
95+
| sum() | Provides the sum value of an array of numbers | Double |
96+
| keys() | Provides the property keys (An alternative for terminal tilde `~`) | `Set<E>` |
97+
| concat(X) | Provides a concatinated version of the path output with a new item | like input |
98+
| append(X) | add an item to the json path output array | like input |
99+
| first() | Provides the first item of an array | Depends on the array |
100+
| last() | Provides the last item of an array | Depends on the array |
101+
| index(X) | Provides the item of an array of index: X, if the X is negative, take from backwards | Depends on the array |
102+
| distinct() | Provides an array containing only unique items from the input array | List<E> |
102103
Filter Operators
103104
-----------------
104105

json-path/src/main/java/com/jayway/jsonpath/internal/function/PathFunctionFactory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.jayway.jsonpath.internal.function.numeric.Min;
99
import com.jayway.jsonpath.internal.function.numeric.StandardDeviation;
1010
import com.jayway.jsonpath.internal.function.numeric.Sum;
11+
import com.jayway.jsonpath.internal.function.sequence.Distinct;
1112
import com.jayway.jsonpath.internal.function.sequence.First;
1213
import com.jayway.jsonpath.internal.function.sequence.Index;
1314
import com.jayway.jsonpath.internal.function.sequence.Last;
@@ -53,6 +54,7 @@ public class PathFunctionFactory {
5354
// Sequential Functions
5455
map.put("first", First.class);
5556
map.put("last", Last.class);
57+
map.put("distinct", Distinct.class);
5658
map.put("index", Index.class);
5759

5860

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.jayway.jsonpath.internal.function.sequence;
2+
3+
import com.jayway.jsonpath.JsonPathException;
4+
import com.jayway.jsonpath.internal.EvaluationContext;
5+
import com.jayway.jsonpath.internal.PathRef;
6+
import com.jayway.jsonpath.internal.function.Parameter;
7+
import com.jayway.jsonpath.internal.function.PathFunction;
8+
9+
import java.util.List;
10+
import java.util.stream.Collectors;
11+
import java.util.stream.StreamSupport;
12+
13+
/**
14+
* Take the unique items from collection of JSONArray
15+
* <p>
16+
* Created by PavelSakharchuk on 21/09/23
17+
*/
18+
public class Distinct implements PathFunction {
19+
20+
@Override
21+
public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {
22+
if (ctx.configuration().jsonProvider().isArray(model)) {
23+
Iterable<?> objects = ctx.configuration().jsonProvider().toIterable(model);
24+
return StreamSupport.stream(objects.spliterator(), false)
25+
.distinct()
26+
.collect(Collectors.toList());
27+
}
28+
throw new JsonPathException("Aggregation function attempted unique values using non array");
29+
}
30+
}

json-path/src/test/java/com/jayway/jsonpath/internal/function/BaseFunctionTest.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,19 @@
1313
*/
1414
public class BaseFunctionTest {
1515
protected static final String NUMBER_SERIES = "{\"empty\": [], \"numbers\" : [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}";
16-
protected static final String TEXT_SERIES = "{\"urls\": [\"http://api.worldbank.org/countries/all/?format=json\", \"http://api.worldbank.org/countries/all/?format=json\"], \"text\" : [ \"a\", \"b\", \"c\", \"d\", \"e\", \"f\" ]}";
16+
protected static final String TEXT_SERIES = "{\"urls\": [\"http://api.worldbank.org/countries/all/?format=json\", \"http://api.worldbank.org/countries/all/?format=json\"], \"text\" : [ \"a\", \"b\", \"c\", \"d\", \"e\", \"f\" ], \"text_with_duplicates\" : [ \"a\", \"b\", \"b\" ]}";
1717
protected static final String TEXT_AND_NUMBER_SERIES = "{\"text\" : [ \"a\", \"b\", \"c\", \"d\", \"e\", \"f\" ], \"numbers\" : [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}";
18+
protected static final String OBJECT_SERIES = "{\"empty\":[]," +
19+
"\"objects\":[{\"a\": \"a-val\"}, {\"b\":\"b-val\"},{ \"a\":\"a-val\"}]," +
20+
"\"array_of_objects\":[" +
21+
"{\"a\":[{\"a\":\"a-val\"},{\"b\":\"b-val\"}]}," +
22+
"{\"b\":[{\"b\":\"b-val\"}]}," +
23+
"{\"a\":[{\"a\":\"a-val\"},{\"b\":\"b-val\"}]}]," +
24+
"\"array_of_arrays\":[" +
25+
"[{\"a\":\"a-val\"},{\"b\":\"b-val\"}]," +
26+
"[{\"b\":\"b-val\"}]," +
27+
"[{\"a\":\"a-val\"},{\"b\":\"b-val\"}]]" +
28+
"}";
1829

1930
/**
2031
* Verify the function returns the correct result based on the input expectedValue

json-path/src/test/java/com/jayway/jsonpath/internal/function/SequentialPathFunctionTest.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
package com.jayway.jsonpath.internal.function;
22

3+
import static com.jayway.jsonpath.JsonPath.using;
4+
5+
import com.fasterxml.jackson.databind.ObjectMapper;
36
import com.jayway.jsonpath.Configuration;
47
import com.jayway.jsonpath.Configurations;
8+
import java.util.Arrays;
9+
10+
import com.jayway.jsonpath.spi.json.JacksonJsonProvider;
11+
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
512
import org.junit.Test;
613

714
/**
@@ -10,6 +17,7 @@
1017
* -first
1118
* -last
1219
* -index(X)
20+
* -distinct
1321
*
1422
* Created by git9527 on 6/11/22.
1523
*/
@@ -50,4 +58,36 @@ public void testIndexOfText() throws Exception {
5058
verifyFunction(conf, "$.text.index(-1)", TEXT_SERIES, "f");
5159
verifyFunction(conf, "$.text.index(1)", TEXT_SERIES, "b");
5260
}
61+
62+
@Test
63+
public void testDistinctOfText() {
64+
verifyFunction(conf, "$.text_with_duplicates.distinct()", TEXT_SERIES, Arrays.asList("a", "b"));
65+
}
66+
67+
@Test
68+
public void testDistinctOfObjects() {
69+
final Object expectedValue = Configuration.defaultConfiguration().jsonProvider()
70+
.parse("[{\"a\":\"a-val\"}, {\"b\":\"b-val\"}]");
71+
verifyFunction(conf, "$.objects.distinct()", OBJECT_SERIES, expectedValue);
72+
}
73+
74+
@Test
75+
public void testDistinctArrayOfObjects() {
76+
final Object expectedValue = Configuration.defaultConfiguration().jsonProvider()
77+
.parse("[{\"a\":[{\"a\":\"a-val\"}, {\"b\":\"b-val\"}]}, {\"b\":[{\"b\":\"b-val\"}]}]");
78+
verifyFunction(conf, "$.array_of_objects.distinct()", OBJECT_SERIES, expectedValue);
79+
}
80+
81+
@Test
82+
public void testDistinctArrayOfArrays() {
83+
final Object expectedValue = Configuration.defaultConfiguration().jsonProvider()
84+
.parse("[[{\"a\":\"a-val\"}, {\"b\":\"b-val\"}], [{\"b\":\"b-val\"}]]");
85+
verifyFunction(conf, "$.array_of_arrays.distinct()", OBJECT_SERIES, expectedValue);
86+
}
87+
88+
@Test
89+
public void testDistinctOfEmptyObjects() throws Exception {
90+
final Object expectedValue = Configuration.defaultConfiguration().jsonProvider().parse("[]");
91+
verifyFunction(conf, "$.empty.distinct()", OBJECT_SERIES, expectedValue);
92+
}
5393
}

0 commit comments

Comments
 (0)