Skip to content

Commit

Permalink
Defines the pattern for taking unique items from collection of JSONArray
Browse files Browse the repository at this point in the history
  • Loading branch information
PavelSakharchuk committed Oct 2, 2023
1 parent 21de620 commit e707a46
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 15 deletions.
29 changes: 15 additions & 14 deletions README.md
Expand Up @@ -85,20 +85,21 @@ 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 |
| 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 |
| distinct() | Provides an array containing only unique items from the input array | List<E> |
Filter Operators
-----------------

Expand Down
Expand Up @@ -8,6 +8,7 @@
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.sequence.Distinct;
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 @@ -53,6 +54,7 @@ public class PathFunctionFactory {
// Sequential Functions
map.put("first", First.class);
map.put("last", Last.class);
map.put("distinct", Distinct.class);
map.put("index", Index.class);


Expand Down
@@ -0,0 +1,30 @@
package com.jayway.jsonpath.internal.function.sequence;

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;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
* Take the unique items from collection of JSONArray
* <p>
* Created by PavelSakharchuk on 21/09/23
*/
public class Distinct implements PathFunction {

@Override
public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {
if (ctx.configuration().jsonProvider().isArray(model)) {
Iterable<?> objects = ctx.configuration().jsonProvider().toIterable(model);
return StreamSupport.stream(objects.spliterator(), false)
.distinct()
.collect(Collectors.toList());
}
throw new JsonPathException("Aggregation function attempted unique values using non array");
}
}
Expand Up @@ -13,8 +13,19 @@
*/
public class BaseFunctionTest {
protected static final String NUMBER_SERIES = "{\"empty\": [], \"numbers\" : [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}";
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\" ]}";
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\" ]}";
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]}";
protected static final String OBJECT_SERIES = "{\"empty\":[]," +
"\"objects\":[{\"a\": \"a-val\"}, {\"b\":\"b-val\"},{ \"a\":\"a-val\"}]," +
"\"array_of_objects\":[" +
"{\"a\":[{\"a\":\"a-val\"},{\"b\":\"b-val\"}]}," +
"{\"b\":[{\"b\":\"b-val\"}]}," +
"{\"a\":[{\"a\":\"a-val\"},{\"b\":\"b-val\"}]}]," +
"\"array_of_arrays\":[" +
"[{\"a\":\"a-val\"},{\"b\":\"b-val\"}]," +
"[{\"b\":\"b-val\"}]," +
"[{\"a\":\"a-val\"},{\"b\":\"b-val\"}]]" +
"}";

/**
* Verify the function returns the correct result based on the input expectedValue
Expand Down
@@ -1,7 +1,14 @@
package com.jayway.jsonpath.internal.function;

import static com.jayway.jsonpath.JsonPath.using;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Configurations;
import java.util.Arrays;

import com.jayway.jsonpath.spi.json.JacksonJsonProvider;
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
import org.junit.Test;

/**
Expand All @@ -10,6 +17,7 @@
* -first
* -last
* -index(X)
* -distinct
*
* Created by git9527 on 6/11/22.
*/
Expand Down Expand Up @@ -50,4 +58,36 @@ public void testIndexOfText() throws Exception {
verifyFunction(conf, "$.text.index(-1)", TEXT_SERIES, "f");
verifyFunction(conf, "$.text.index(1)", TEXT_SERIES, "b");
}

@Test
public void testDistinctOfText() {
verifyFunction(conf, "$.text_with_duplicates.distinct()", TEXT_SERIES, Arrays.asList("a", "b"));
}

@Test
public void testDistinctOfObjects() {
final Object expectedValue = Configuration.defaultConfiguration().jsonProvider()
.parse("[{\"a\":\"a-val\"}, {\"b\":\"b-val\"}]");
verifyFunction(conf, "$.objects.distinct()", OBJECT_SERIES, expectedValue);
}

@Test
public void testDistinctArrayOfObjects() {
final Object expectedValue = Configuration.defaultConfiguration().jsonProvider()
.parse("[{\"a\":[{\"a\":\"a-val\"}, {\"b\":\"b-val\"}]}, {\"b\":[{\"b\":\"b-val\"}]}]");
verifyFunction(conf, "$.array_of_objects.distinct()", OBJECT_SERIES, expectedValue);
}

@Test
public void testDistinctArrayOfArrays() {
final Object expectedValue = Configuration.defaultConfiguration().jsonProvider()
.parse("[[{\"a\":\"a-val\"}, {\"b\":\"b-val\"}], [{\"b\":\"b-val\"}]]");
verifyFunction(conf, "$.array_of_arrays.distinct()", OBJECT_SERIES, expectedValue);
}

@Test
public void testDistinctOfEmptyObjects() throws Exception {
final Object expectedValue = Configuration.defaultConfiguration().jsonProvider().parse("[]");
verifyFunction(conf, "$.empty.distinct()", OBJECT_SERIES, expectedValue);
}
}

0 comments on commit e707a46

Please sign in to comment.