Browse Source

adds an example for HttpLoading via getjson (not intended to be merged, just an example) also fixes bug #164 min/max providing wrong value

pull/167/head
Matthew J Greenwood 9 years ago
parent
commit
b919644425
  1. 4
      json-path/src/main/java/com/jayway/jsonpath/internal/function/PathFunctionFactory.java
  2. 49
      json-path/src/main/java/com/jayway/jsonpath/internal/function/http/HttpLoader.java
  3. 9
      json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/AbstractAggregation.java
  4. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/path/EvaluationContextImpl.java
  5. 5
      json-path/src/main/java/com/jayway/jsonpath/internal/path/FunctionPathToken.java
  6. 14
      json-path/src/main/java/com/jayway/jsonpath/spi/json/AbstractJsonProvider.java
  7. 7
      json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java
  8. 4
      json-path/src/test/java/com/jayway/jsonpath/internal/function/BaseFunctionTest.java
  9. 5
      json-path/src/test/java/com/jayway/jsonpath/internal/function/NestedFunctionTest.java
  10. 48
      json-path/src/test/java/com/jayway/jsonpath/internal/function/NumericPathFunctionTest.java

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

@ -1,6 +1,7 @@
package com.jayway.jsonpath.internal.function;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.internal.function.http.HttpLoader;
import com.jayway.jsonpath.internal.function.numeric.Average;
import com.jayway.jsonpath.internal.function.numeric.Max;
import com.jayway.jsonpath.internal.function.numeric.Min;
@ -40,6 +41,9 @@ public class PathFunctionFactory {
// Text Functions
map.put("concat", Concatenate.class);
// Network functions
map.put("getjson", HttpLoader.class);
// JSON Entity Functions
map.put("length", Length.class);
map.put("size", Length.class);

49
json-path/src/main/java/com/jayway/jsonpath/internal/function/http/HttpLoader.java

@ -0,0 +1,49 @@
package com.jayway.jsonpath.internal.function.http;
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.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.List;
/**
* Dirt simple http get method just to demo URL loading
*
* Created by mgreenwood on 12/11/15.
*/
public class HttpLoader implements PathFunction {
@Override
public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {
if (parameters != null && parameters.size() == 1) {
try {
URL url = new URL(parameters.get(0).getCachedValue().toString());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
StringBuffer result = new StringBuffer();
while ((line = rd.readLine()) != null) {
result.append(line);
}
rd.close();
Object jsonResult = ctx.configuration().jsonProvider().parse(result.toString());
return jsonResult;
} catch (ProtocolException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}

9
json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/AbstractAggregation.java

@ -1,5 +1,6 @@
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;
@ -34,12 +35,14 @@ public abstract class AbstractAggregation implements PathFunction {
@Override
public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {
int count = 0;
if(ctx.configuration().jsonProvider().isArray(model)){
Iterable<?> objects = ctx.configuration().jsonProvider().toIterable(model);
for (Object obj : objects) {
if (obj instanceof Number) {
Number value = (Number) obj;
count++;
next(value);
}
}
@ -48,10 +51,14 @@ public abstract class AbstractAggregation implements PathFunction {
for (Parameter param : parameters) {
if (param.getCachedValue() instanceof Number) {
Number value = (Number)param.getCachedValue();
count++;
next(value);
}
}
}
return getValue();
if (count != 0) {
return getValue();
}
throw new JsonPathException("Aggregation function attempted to calculate value using empty array");
}
}

2
json-path/src/main/java/com/jayway/jsonpath/internal/path/EvaluationContextImpl.java

@ -130,7 +130,7 @@ public class EvaluationContextImpl implements EvaluationContext {
if(resultIndex == 0){
throw new PathNotFoundException("No results for path: " + path.toString());
}
Object value = jsonProvider().getArrayIndex(valueResult, 0);
Object value = jsonProvider().getLastElement(valueResult);
if (value != null && unwrap){
value = jsonProvider().unwrap(value);
}

5
json-path/src/main/java/com/jayway/jsonpath/internal/path/FunctionPathToken.java

@ -36,7 +36,10 @@ public class FunctionPathToken extends PathToken {
PathFunction pathFunction = PathFunctionFactory.newFunction(functionName);
evaluateParameters(currentPath, parent, model, ctx);
Object result = pathFunction.invoke(currentPath, parent, model, ctx, functionParams);
ctx.addResult(currentPath, parent, result);
ctx.addResult(currentPath + "." + functionName, parent, result);
if (!isLeaf()) {
next().evaluate(currentPath, parent, result, ctx);
}
}
private void evaluateParameters(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {

14
json-path/src/main/java/com/jayway/jsonpath/spi/json/AbstractJsonProvider.java

@ -43,6 +43,20 @@ public abstract class AbstractJsonProvider implements JsonProvider {
return ((List) obj).get(idx);
}
/**
* Extracts the last value from an array
*
* @param obj an array
* @return the entry at the given index
*/
public Object getLastElement(Object obj) {
if (null != obj) {
int len = this.length(obj);
return unwrap(getArrayIndex(obj, len-1));
}
return null;
}
public final Object getArrayIndex(Object obj, int idx, boolean unwrap){
return getArrayIndex(obj, idx);
}

7
json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java

@ -165,4 +165,11 @@ public interface JsonProvider {
Object unwrap(Object obj);
/**
* Get the last element of the array
*
* @param obj an array
* @return the unwrapped value
*/
Object getLastElement(Object obj);
}

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

@ -12,8 +12,8 @@ import static org.assertj.core.api.Assertions.assertThat;
* Created by mattg on 6/27/15.
*/
public class BaseFunctionTest {
protected static final String NUMBER_SERIES = "{\"numbers\" : [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}";
protected static final String TEXT_SERIES = "{\"text\" : [ \"a\", \"b\", \"c\", \"d\", \"e\", \"f\" ]}";
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\" ]}";

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

@ -64,4 +64,9 @@ public class NestedFunctionTest extends BaseFunctionTest {
public void testStringConcatWithJSONParameter() {
verifyTextFunction(conf, "$.text.concat(\"-\", \"ghijk\")", "abcdef-ghijk");
}
@Test
public void testLoadFunction() {
verifyTextFunction(conf, "$.getjson($.urls[0])[0].total", 264);
}
}

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

@ -2,12 +2,14 @@ package com.jayway.jsonpath.internal.function;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Configurations;
import com.jayway.jsonpath.JsonPathException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.junit.Assert.assertEquals;
import static org.junit.runners.Parameterized.Parameters;
/**
@ -45,26 +47,72 @@ public class NumericPathFunctionTest extends BaseFunctionTest {
verifyMathFunction(conf, "$.numbers.avg()", 5.5);
}
@Test
public void testAverageOfEmptyListNegative() {
try {
verifyMathFunction(conf, "$.empty.avg()", null);
} catch (JsonPathException e) {
assertEquals(e.getMessage(), "Aggregation function attempted to calculate value using empty array");
}
}
@Test
public void testSumOfDouble() {
verifyMathFunction(conf, "$.numbers.sum()", (10d * (10d + 1d)) / 2d);
}
@Test
public void testSumOfEmptyListNegative() {
try {
verifyMathFunction(conf, "$.empty.sum()", null);
} catch (JsonPathException e) {
assertEquals(e.getMessage(), "Aggregation function attempted to calculate value using empty array");
}
}
@Test
public void testMaxOfDouble() {
verifyMathFunction(conf, "$.numbers.max()", 10d);
}
@Test
public void testMaxOfEmptyListNegative() {
try {
verifyMathFunction(conf, "$.empty.max()", null);
} catch (JsonPathException e) {
assertEquals(e.getMessage(), "Aggregation function attempted to calculate value using empty array");
}
}
@Test
public void testMinOfDouble() {
verifyMathFunction(conf, "$.numbers.min()", 1d);
}
@Test
public void testMinOfEmptyListNegative() {
try {
verifyMathFunction(conf, "$.empty.min()", null);
} catch (JsonPathException e) {
assertEquals(e.getMessage(), "Aggregation function attempted to calculate value using empty array");
}
}
@Test
public void testStdDevOfDouble() {
verifyMathFunction(conf, "$.numbers.stddev()", 2.8722813232690143d);
}
@Test
public void testStddevOfEmptyListNegative() {
try {
verifyMathFunction(conf, "$.empty.stddev()", null);
} catch (JsonPathException e) {
assertEquals(e.getMessage(), "Aggregation function attempted to calculate value using empty array");
}
}
/**
* Expect that for an invalid function name we'll get back the original input to the function
*/

Loading…
Cancel
Save