Skip to content

Commit

Permalink
Defines the pattern for taking item from collection of JSONArray by i…
Browse files Browse the repository at this point in the history
…ndex (#842)
  • Loading branch information
git9527 authored Oct 27, 2022
1 parent 2eed3b9 commit 9729cb0
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 14 deletions.
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,20 @@ 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 |

| 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 |
Filter Operators
-----------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
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.First;
import com.jayway.jsonpath.internal.function.sequence.Index;
import com.jayway.jsonpath.internal.function.sequence.Last;
import com.jayway.jsonpath.internal.function.text.Concatenate;
import com.jayway.jsonpath.internal.function.text.Length;

Expand Down Expand Up @@ -46,6 +49,11 @@ public class PathFunctionFactory {
map.put("size", Length.class);
map.put("append", Append.class);
map.put("keys", KeySetFunction.class);

// Sequential Functions
map.put("first", First.class);
map.put("last", Last.class);
map.put("index", Index.class);


FUNCTIONS = Collections.unmodifiableMap(map);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
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.ArrayList;
import java.util.List;

/**
* Defines the pattern for taking item from collection of JSONArray by index
*
* Created by git9527 on 6/11/22.
*/
public abstract class AbstractSequenceAggregation implements PathFunction {

protected abstract int targetIndex(EvaluationContext ctx, List<Parameter> parameters);

@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);
List<Object> objectList = new ArrayList<>();
objects.forEach(objectList::add);
int targetIndex = this.targetIndex(ctx, parameters);
if (targetIndex >= 0) {
return objectList.get(targetIndex);
} else {
int realIndex = objectList.size() + targetIndex;
if (realIndex > 0) {
return objectList.get(realIndex);
} else {
throw new JsonPathException("Target index:" + targetIndex + " larger than object count:" + objectList.size());
}
}
}
throw new JsonPathException("Aggregation function attempted to calculate value using empty array");
}

protected int getIndexFromParameters(EvaluationContext ctx, List<Parameter> parameters) {
List<Number> numbers = Parameter.toList(Number.class, ctx, parameters);
return numbers.get(0).intValue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.jayway.jsonpath.internal.function.sequence;

import com.jayway.jsonpath.internal.EvaluationContext;
import com.jayway.jsonpath.internal.function.Parameter;

import java.util.List;

/**
* Take the first item from collection of JSONArray
*
* Created by git9527 on 6/11/22.
*/
public class First extends AbstractSequenceAggregation {
@Override
protected int targetIndex(EvaluationContext ctx, List<Parameter> parameters) {
return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.jayway.jsonpath.internal.function.sequence;

import com.jayway.jsonpath.internal.EvaluationContext;
import com.jayway.jsonpath.internal.function.Parameter;

import java.util.List;

/**
* Take the index from first Parameter, then the item from collection of JSONArray by index
*
* Created by git9527 on 6/11/22.
*/
public class Index extends AbstractSequenceAggregation {
@Override
protected int targetIndex(EvaluationContext ctx, List<Parameter> parameters) {
return getIndexFromParameters(ctx, parameters);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.jayway.jsonpath.internal.function.sequence;

import com.jayway.jsonpath.internal.EvaluationContext;
import com.jayway.jsonpath.internal.function.Parameter;

import java.util.List;

/**
* Take the first item from collection of JSONArray
*
* Created by git9527 on 6/11/22.
*/
public class Last extends AbstractSequenceAggregation {
@Override
protected int targetIndex(EvaluationContext ctx, List<Parameter> parameters) {
return -1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ private List<Parameter> parseFunctionParameters(String funcName) {
continue;
}

if (c == OPEN_BRACE || isDigit(c) || DOUBLE_QUOTE == c) {
if (c == OPEN_BRACE || isDigit(c) || DOUBLE_QUOTE == c || MINUS == c) {
type = ParamType.JSON;
}
else if (isPathContext(c)) {
Expand Down Expand Up @@ -612,7 +612,7 @@ private boolean readBracketPropertyToken(PathTokenAppender appender) {
inProperty = true;
lastSignificantWasComma = false;
}
} else if (c == COMMA && !inProperty) {
} else if (c == COMMA && !inProperty) {
if (lastSignificantWasComma){
fail("Found empty property at index "+readPosition);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.jayway.jsonpath.internal.function;

import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Configurations;
import org.junit.Test;

/**
* Test cases for functions
*
* -first
* -last
* -index(X)
*
* Created by git9527 on 6/11/22.
*/
public class SequentialPathFunctionTest extends BaseFunctionTest {

private Configuration conf = Configurations.JACKSON_CONFIGURATION;

@Test
public void testFirstOfNumbers() throws Exception {
verifyFunction(conf, "$.numbers.first()", NUMBER_SERIES, 1);
}

@Test
public void testLastOfNumbers() throws Exception {
verifyFunction(conf, "$.numbers.last()", NUMBER_SERIES, 10);
}

@Test
public void testIndexOfNumbers() throws Exception {
verifyFunction(conf, "$.numbers.index(0)", NUMBER_SERIES, 1);
verifyFunction(conf, "$.numbers.index(-1)", NUMBER_SERIES, 10);
verifyFunction(conf, "$.numbers.index(1)", NUMBER_SERIES, 2);
}

@Test
public void testFirstOfText() throws Exception {
verifyFunction(conf, "$.text.first()", TEXT_SERIES, "a");
}

@Test
public void testLastOfText() throws Exception {
verifyFunction(conf, "$.text.last()", TEXT_SERIES, "f");
}

@Test
public void testIndexOfText() throws Exception {
verifyFunction(conf, "$.text.index(0)", TEXT_SERIES, "a");
verifyFunction(conf, "$.text.index(-1)", TEXT_SERIES, "f");
verifyFunction(conf, "$.text.index(1)", TEXT_SERIES, "b");
}
}

0 comments on commit 9729cb0

Please sign in to comment.