Browse Source

Defines the pattern for taking item from collection of JSONArray by index (#842)

pull/869/head
zhangsn 2 years ago committed by GitHub
parent
commit
9729cb048b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 26
      README.md
  2. 8
      json-path/src/main/java/com/jayway/jsonpath/internal/function/PathFunctionFactory.java
  3. 47
      json-path/src/main/java/com/jayway/jsonpath/internal/function/sequence/AbstractSequenceAggregation.java
  4. 18
      json-path/src/main/java/com/jayway/jsonpath/internal/function/sequence/First.java
  5. 18
      json-path/src/main/java/com/jayway/jsonpath/internal/function/sequence/Index.java
  6. 18
      json-path/src/main/java/com/jayway/jsonpath/internal/function/sequence/Last.java
  7. 4
      json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java
  8. 53
      json-path/src/test/java/com/jayway/jsonpath/internal/function/SequentialPathFunctionTest.java

26
README.md

@ -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
-----------------

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

@ -8,6 +8,9 @@ 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.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;
@ -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);

47
json-path/src/main/java/com/jayway/jsonpath/internal/function/sequence/AbstractSequenceAggregation.java

@ -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();
}
}

18
json-path/src/main/java/com/jayway/jsonpath/internal/function/sequence/First.java

@ -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;
}
}

18
json-path/src/main/java/com/jayway/jsonpath/internal/function/sequence/Index.java

@ -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);
}
}

18
json-path/src/main/java/com/jayway/jsonpath/internal/function/sequence/Last.java

@ -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;
}
}

4
json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java

@ -305,7 +305,7 @@ public class PathCompiler {
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)) {
@ -612,7 +612,7 @@ public class PathCompiler {
inProperty = true;
lastSignificantWasComma = false;
}
} else if (c == COMMA && !inProperty) {
} else if (c == COMMA && !inProperty) {
if (lastSignificantWasComma){
fail("Found empty property at index "+readPosition);
}

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

@ -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");
}
}
Loading…
Cancel
Save