Browse Source

Merge branch 'master' into use-json-smart-for-query-parsing

pull/314/head
jochenberger 8 years ago committed by GitHub
parent
commit
2a16517f61
  1. 2
      README.md
  2. 4
      build.gradle
  3. BIN
      gradle/wrapper/gradle-wrapper.jar
  4. 4
      gradle/wrapper/gradle-wrapper.properties
  5. 68
      gradlew
  6. 12
      gradlew.bat
  7. 2
      json-path-assert/build.gradle
  8. 16
      json-path-web-test/build.gradle
  9. 18
      json-path/build.gradle
  10. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/JsonContext.java
  11. 15
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java
  12. 10
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/LogicalExpressionNode.java
  13. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/LogicalOperator.java
  14. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java
  15. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/path/EvaluationContextImpl.java
  16. 48
      json-path/src/main/java/com/jayway/jsonpath/spi/json/GsonJsonProvider.java
  17. 4
      json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonOrgJsonProvider.java
  18. 61
      json-path/src/test/java/com/jayway/jsonpath/GsonJsonProviderTest.java

2
README.md

@ -256,6 +256,8 @@ List<Map<String, Object>> books = JsonPath.parse(json)
You can use `&&` and `||` to combine multiple predicates `[?(@.price < 10 && @.category == 'fiction')]` , You can use `&&` and `||` to combine multiple predicates `[?(@.price < 10 && @.category == 'fiction')]` ,
`[?(@.category == 'reference' || @.price > 10)]`. `[?(@.category == 'reference' || @.price > 10)]`.
You can use `!` to negate a predicate `[?(!(@.price < 10 && @.category == 'fiction'))]`.
###Filter Predicates ###Filter Predicates
Predicates can be built using the Filter API as shown below: Predicates can be built using the Filter API as shown below:

4
build.gradle

@ -17,7 +17,7 @@ ext {
gson: 'com.google.code.gson:gson:2.3.1', gson: 'com.google.code.gson:gson:2.3.1',
jettison: 'org.codehaus.jettison:jettison:1.3.7', jettison: 'org.codehaus.jettison:jettison:1.3.7',
jsonOrg: 'org.json:json:20140107', jsonOrg: 'org.json:json:20140107',
tapestryJson: 'org.apache.tapestry:tapestry-json:5.4.0', tapestryJson: 'org.apache.tapestry:tapestry-json:5.4.1',
hamcrestCore: 'org.hamcrest:hamcrest-core:1.3', hamcrestCore: 'org.hamcrest:hamcrest-core:1.3',
hamcrestLibrary: 'org.hamcrest:hamcrest-library:1.3', hamcrestLibrary: 'org.hamcrest:hamcrest-library:1.3',
@ -73,7 +73,7 @@ subprojects {
} }
task wrapper(type: Wrapper) { task wrapper(type: Wrapper) {
gradleVersion = '2.11' gradleVersion = '3.4.1'
} }
//Task used by Heroku for staging //Task used by Heroku for staging

BIN
gradle/wrapper/gradle-wrapper.jar vendored

Binary file not shown.

4
gradle/wrapper/gradle-wrapper.properties vendored

@ -1,6 +1,6 @@
#Fri Feb 12 10:36:51 CET 2016 #Fri Mar 17 10:32:10 CET 2017
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-bin.zip

68
gradlew vendored

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env sh
############################################################################## ##############################################################################
## ##
@ -6,12 +6,30 @@
## ##
############################################################################## ##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # Attempt to set APP_HOME
DEFAULT_JVM_OPTS="" # Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle" APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"` APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD="maximum"
@ -30,6 +48,7 @@ die ( ) {
cygwin=false cygwin=false
msys=false msys=false
darwin=false darwin=false
nonstop=false
case "`uname`" in case "`uname`" in
CYGWIN* ) CYGWIN* )
cygwin=true cygwin=true
@ -40,26 +59,11 @@ case "`uname`" in
MINGW* ) MINGW* )
msys=true msys=true
;; ;;
NONSTOP* )
nonstop=true
;;
esac esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
@ -85,7 +89,7 @@ location of your Java installation."
fi fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n` MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@ -150,11 +154,19 @@ if $cygwin ; then
esac esac
fi fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules # Escape application args
function splitJvmOpts() { save ( ) {
JVM_OPTS=("$@") for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
} }
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS APP_ARGS=$(save "$@")
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" exec "$JAVACMD" "$@"

12
gradlew.bat vendored

@ -8,14 +8,14 @@
@rem Set local scope for the variables with windows NT shell @rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=. if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
@ -49,7 +49,6 @@ goto fail
@rem Get command-line arguments, handling Windows variants @rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args :win9xME_args
@rem Slurp the command line arguments. @rem Slurp the command line arguments.
@ -60,11 +59,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%* set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute :execute
@rem Setup the command line @rem Setup the command line

2
json-path-assert/build.gradle

@ -1,7 +1,5 @@
apply from: "$rootDir/gradle/publishMaven.gradle" apply from: "$rootDir/gradle/publishMaven.gradle"
displayName = "JsonPath Assert"
description = "Assertions on Json using JsonPath" description = "Assertions on Json using JsonPath"
jar { jar {

16
json-path-web-test/build.gradle

@ -1,18 +1,18 @@
apply plugin: 'com.github.johnrengelman.shadow' apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'application' apply plugin: 'application'
displayName = "JsonPath Test Bench"
description = "Web app that compares different JsonPath implementations." description = "Web app that compares different JsonPath implementations."
mainClassName = 'com.jayway.jsonpath.web.boot.Main' mainClassName = 'com.jayway.jsonpath.web.boot.Main'
task createBuildInfoFile << { task createBuildInfoFile {
def buildInfoFile = new File("$buildDir/classes/main/build-info.properties") doLast {
Properties props = new Properties() def buildInfoFile = new File("$buildDir/classes/main/build-info.properties")
props.setProperty('version', project.version.toString()) Properties props = new Properties()
props.setProperty('timestamp', project.buildTimestamp) props.setProperty('version', project.version.toString())
props.store(buildInfoFile.newWriter(), null) props.setProperty('timestamp', project.buildTimestamp)
props.store(buildInfoFile.newWriter(), null)
}
} }
jar { jar {

18
json-path/build.gradle

@ -1,20 +1,20 @@
apply from: "$rootDir/gradle/publishMaven.gradle" apply from: "$rootDir/gradle/publishMaven.gradle"
displayName = "Json Path"
description = "Java port of Stefan Goessner JsonPath." description = "Java port of Stefan Goessner JsonPath."
jar { jar {
baseName 'json-path' baseName 'json-path'
manifest { manifest {
attributes 'Implementation-Title': 'json-path', 'Implementation-Version': version attributes 'Implementation-Title': 'json-path', 'Implementation-Version': version
instruction 'Import-Package', 'org.json.*;resolution:=optional', 'com.google.gson.*;resolution:=optional', 'com.fasterxml.jackson.*;resolution:=optional', 'org.apache.tapestry5.json.*;resolution:=optional', '*' instruction 'Import-Package', 'org.json.*;resolution:=optional', 'com.google.gson.*;resolution:=optional', 'com.fasterxml.jackson.*;resolution:=optional', 'org.apache.tapestry5.json.*;resolution:=optional', 'org.codehaus.jettison.*;resolution:=optional', '*'
} }
} }
dependencies { dependencies {
compile libs.jsonSmart compile (libs.jsonSmart){
// see https://github.com/jayway/JsonPath/issues/228, https://github.com/netplex/json-smart-v2/issues/20
exclude group: 'org.ow2.asm', module: 'asm'
}
compile libs.slf4jApi compile libs.slf4jApi
compile libs.jacksonDatabind, optional compile libs.jacksonDatabind, optional
compile libs.gson, optional compile libs.gson, optional
@ -39,7 +39,7 @@ task distZip(type: Zip, dependsOn: assemble) {
} }
from(project.configurations.compile) { from(project.configurations.compile) {
into 'lib' into 'lib'
exclude { it.file.name.contains('gson') || it.file.name.contains('jackson') || it.file.name.contains('json-2') || it.file.name.contains('jettison') } exclude { it.file.name.contains('gson') || it.file.name.contains('jackson') || it.file.name.contains('json-2') || it.file.name.contains('jettison') || it.file.name.contains('tapestry') }
} }
from(project.configurations.compile) { from(project.configurations.compile) {
into 'lib-optional/jackson' into 'lib-optional/jackson'
@ -58,7 +58,7 @@ task distZip(type: Zip, dependsOn: assemble) {
include { it.file.name.contains('json-2') } include { it.file.name.contains('json-2') }
} }
from(project.configurations.compile) { from(project.configurations.compile) {
into 'lib-optional/jsonOrg' into 'lib-optional/tapestry'
include { it.file.name.contains('tapestry') } include { it.file.name.contains('tapestry') }
} }
} }
@ -79,7 +79,7 @@ task distTar(type: Tar, dependsOn: assemble) {
} }
from(project.configurations.compile) { from(project.configurations.compile) {
into 'lib' into 'lib'
exclude { it.file.name.contains('gson') || it.file.name.contains('jackson') || it.file.name.contains('json-2') || it.file.name.contains('jettison') } exclude { it.file.name.contains('gson') || it.file.name.contains('jackson') || it.file.name.contains('json-2') || it.file.name.contains('jettison') || it.file.name.contains('tapestry') }
} }
from(project.configurations.compile) { from(project.configurations.compile) {
into 'lib-optional/jackson' into 'lib-optional/jackson'
@ -98,7 +98,7 @@ task distTar(type: Tar, dependsOn: assemble) {
include { it.file.name.contains('json-2') } include { it.file.name.contains('json-2') }
} }
from(project.configurations.compile) { from(project.configurations.compile) {
into 'lib-optional/jsonOrg' into 'lib-optional/tapestry'
include { it.file.name.contains('tapestry') } include { it.file.name.contains('tapestry') }
} }
} }

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

@ -289,7 +289,7 @@ public class JsonContext implements ParseContext, DocumentContext {
return this; return this;
} }
private final class LimitingEvaluationListener implements EvaluationListener { private final static class LimitingEvaluationListener implements EvaluationListener {
final int limit; final int limit;
private LimitingEvaluationListener(int limit) { private LimitingEvaluationListener(int limit) {

15
json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java

@ -120,7 +120,7 @@ public class FilterCompiler {
/* /*
* LogicalOR = LogicalAND { '||' LogicalAND } * LogicalOR = LogicalAND { '||' LogicalAND }
* LogicalAND = LogicalANDOperand { '&&' LogicalANDOperand } * LogicalAND = LogicalANDOperand { '&&' LogicalANDOperand }
* LogicalANDOperand = RelationalExpression | '(' LogicalOR ')' * LogicalANDOperand = RelationalExpression | '(' LogicalOR ')' | '!' LogicalANDOperand
* RelationalExpression = Value [ RelationalOperator Value ] * RelationalExpression = Value [ RelationalOperator Value ]
*/ */
@ -164,6 +164,19 @@ public class FilterCompiler {
} }
private ExpressionNode readLogicalANDOperand() { private ExpressionNode readLogicalANDOperand() {
int savepoint = filter.skipBlanks().position();
if (filter.skipBlanks().currentCharIs(NOT)) {
filter.readSignificantChar(NOT);
switch (filter.skipBlanks().currentChar()) {
case DOC_CONTEXT:
case EVAL_CONTEXT:
filter.setPosition(savepoint);
break;
default:
final ExpressionNode op = readLogicalANDOperand();
return LogicalExpressionNode.createLogicalNot(op);
}
}
if (filter.skipBlanks().currentCharIs(OPEN_PARENTHESIS)) { if (filter.skipBlanks().currentCharIs(OPEN_PARENTHESIS)) {
filter.readSignificantChar(OPEN_PARENTHESIS); filter.readSignificantChar(OPEN_PARENTHESIS);
final ExpressionNode op = readLogicalOR(); final ExpressionNode op = readLogicalOR();

10
json-path/src/main/java/com/jayway/jsonpath/internal/filter/LogicalExpressionNode.java

@ -10,6 +10,10 @@ public class LogicalExpressionNode extends ExpressionNode {
protected List<ExpressionNode> chain = new ArrayList<ExpressionNode>(); protected List<ExpressionNode> chain = new ArrayList<ExpressionNode>();
private final LogicalOperator operator; private final LogicalOperator operator;
public static ExpressionNode createLogicalNot(ExpressionNode op) {
return new LogicalExpressionNode(op, LogicalOperator.NOT, null);
}
public static LogicalExpressionNode createLogicalOr(ExpressionNode left,ExpressionNode right){ public static LogicalExpressionNode createLogicalOr(ExpressionNode left,ExpressionNode right){
return new LogicalExpressionNode(left, LogicalOperator.OR, right); return new LogicalExpressionNode(left, LogicalOperator.OR, right);
} }
@ -68,13 +72,17 @@ public class LogicalExpressionNode extends ExpressionNode {
} }
} }
return false; return false;
} else { } else if (operator == LogicalOperator.AND) {
for (ExpressionNode expression : chain) { for (ExpressionNode expression : chain) {
if(!expression.apply(ctx)){ if(!expression.apply(ctx)){
return false; return false;
} }
} }
return true; return true;
} else {
ExpressionNode expression = chain.get(0);
return !expression.apply(ctx);
} }
} }
} }

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

@ -5,6 +5,7 @@ import com.jayway.jsonpath.InvalidPathException;
public enum LogicalOperator { public enum LogicalOperator {
AND("&&"), AND("&&"),
NOT("!"),
OR("||"); OR("||");
private final String operatorString; private final String operatorString;
@ -24,6 +25,7 @@ public enum LogicalOperator {
public static LogicalOperator fromString(String operatorString){ public static LogicalOperator fromString(String operatorString){
if(AND.operatorString.equals(operatorString)) return AND; if(AND.operatorString.equals(operatorString)) return AND;
else if(NOT.operatorString.equals(operatorString)) return NOT;
else if(OR.operatorString.equals(operatorString)) return OR; else if(OR.operatorString.equals(operatorString)) return OR;
else throw new InvalidPathException("Failed to parse operator " + operatorString); else throw new InvalidPathException("Failed to parse operator " + operatorString);
} }

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

@ -810,9 +810,9 @@ public abstract class ValueNode {
} }
public ValueNode evaluate(Predicate.PredicateContext ctx) { public ValueNode evaluate(Predicate.PredicateContext ctx) {
Configuration c = Configuration.builder().jsonProvider(ctx.configuration().jsonProvider()).options(Option.REQUIRE_PROPERTIES).build();
if (isExistsCheck()) { if (isExistsCheck()) {
try { try {
Configuration c = Configuration.builder().jsonProvider(ctx.configuration().jsonProvider()).options(Option.REQUIRE_PROPERTIES).build();
Object result = path.evaluate(ctx.item(), ctx.root(), c).getValue(false); Object result = path.evaluate(ctx.item(), ctx.root(), c).getValue(false);
return result == JsonProvider.UNDEFINED ? ValueNode.FALSE : ValueNode.TRUE; return result == JsonProvider.UNDEFINED ? ValueNode.FALSE : ValueNode.TRUE;
} catch (PathNotFoundException e) { } catch (PathNotFoundException e) {

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

@ -163,7 +163,7 @@ public class EvaluationContextImpl implements EvaluationContext {
return res; return res;
} }
private class FoundResultImpl implements EvaluationListener.FoundResult { private static class FoundResultImpl implements EvaluationListener.FoundResult {
private final int index; private final int index;
private final String path; private final String path;

48
json-path/src/main/java/com/jayway/jsonpath/spi/json/GsonJsonProvider.java

@ -14,28 +14,25 @@
*/ */
package com.jayway.jsonpath.spi.json; package com.jayway.jsonpath.spi.json;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive; import com.google.gson.JsonPrimitive;
import com.google.gson.internal.LazilyParsedNumber;
import com.jayway.jsonpath.InvalidJsonException; import com.jayway.jsonpath.InvalidJsonException;
import com.jayway.jsonpath.JsonPathException; import com.jayway.jsonpath.JsonPathException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class GsonJsonProvider extends AbstractJsonProvider { public class GsonJsonProvider extends AbstractJsonProvider {
private static final JsonParser PARSER = new JsonParser(); private static final JsonParser PARSER = new JsonParser();
@ -86,25 +83,38 @@ public class GsonJsonProvider extends AbstractJsonProvider {
return o; return o;
} }
private static boolean isPrimitiveNumber(final Number n) {
return n instanceof Integer ||
n instanceof Double ||
n instanceof Long ||
n instanceof BigDecimal ||
n instanceof BigInteger;
}
private static Number unwrapNumber(final Number n) { private static Number unwrapNumber(final Number n) {
Number unwrapped; Number unwrapped;
if (n instanceof LazilyParsedNumber) { if (!isPrimitiveNumber(n)) {
LazilyParsedNumber lpn = (LazilyParsedNumber) n; BigDecimal bigDecimal = new BigDecimal(n.toString());
BigDecimal bigDecimal = new BigDecimal(lpn.toString());
if (bigDecimal.scale() <= 0) { if (bigDecimal.scale() <= 0) {
if (bigDecimal.compareTo(new BigDecimal(Integer.MAX_VALUE)) <= 0) { if (bigDecimal.compareTo(new BigDecimal(Integer.MAX_VALUE)) <= 0) {
unwrapped = bigDecimal.intValue(); unwrapped = bigDecimal.intValue();
} else { } else if (bigDecimal.compareTo(new BigDecimal(Long.MAX_VALUE)) <= 0){
unwrapped = bigDecimal.longValue(); unwrapped = bigDecimal.longValue();
} else {
unwrapped = bigDecimal;
} }
} else { } else {
unwrapped = bigDecimal.doubleValue(); final double doubleValue = bigDecimal.doubleValue();
if (BigDecimal.valueOf(doubleValue).compareTo(bigDecimal) != 0) {
unwrapped = bigDecimal;
} else {
unwrapped = doubleValue;
}
} }
} else { } else {
unwrapped = n; unwrapped = n;
} }
return unwrapped; return unwrapped;
} }

4
json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonOrgJsonProvider.java

@ -1,6 +1,6 @@
package com.jayway.jsonpath.spi.json; package com.jayway.jsonpath.spi.json;
import com.google.gson.JsonObject; import org.json.JSONObject;
import com.jayway.jsonpath.InvalidJsonException; import com.jayway.jsonpath.InvalidJsonException;
import com.jayway.jsonpath.JsonPathException; import com.jayway.jsonpath.JsonPathException;
import org.json.JSONArray; import org.json.JSONArray;
@ -62,7 +62,7 @@ public class JsonOrgJsonProvider extends AbstractJsonProvider {
@Override @Override
public Object createMap() { public Object createMap() {
return new JsonObject(); return new JSONObject();
} }
@Override @Override

61
json-path/src/test/java/com/jayway/jsonpath/GsonJsonProviderTest.java

@ -7,6 +7,8 @@ import com.jayway.jsonpath.spi.mapper.MappingException;
import org.junit.Test; import org.junit.Test;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List; import java.util.List;
import static com.jayway.jsonpath.JsonPath.using; import static com.jayway.jsonpath.JsonPath.using;
@ -69,6 +71,65 @@ public class GsonJsonProviderTest extends BaseTest {
assertThat(val).isEqualTo(node.getAsLong()); assertThat(val).isEqualTo(node.getAsLong());
} }
@Test
public void doubles_are_unwrapped() {
final String json = "{double-property = 56.78}";
JsonElement node = using(GSON_CONFIGURATION).parse(json).read("$.double-property");
Double val = using(GSON_CONFIGURATION).parse(json).read("$.double-property", Double.class);
assertThat(val).isEqualTo(56.78);
assertThat(val).isEqualTo(node.getAsDouble());
}
@Test
public void bigdecimals_are_unwrapped() {
final BigDecimal bd = BigDecimal.valueOf(Long.MAX_VALUE).add(BigDecimal.valueOf(10.5));
final String json = "{bd-property = " + bd.toString() + "}";
JsonElement node = using(GSON_CONFIGURATION).parse(json).read("$.bd-property");
BigDecimal val = using(GSON_CONFIGURATION).parse(json).read("$.bd-property", BigDecimal.class);
assertThat(val).isEqualTo(bd);
assertThat(val).isEqualTo(node.getAsBigDecimal());
}
@Test
public void small_bigdecimals_are_unwrapped() {
final BigDecimal bd = BigDecimal.valueOf(10.5);
final String json = "{bd-property = " + bd.toString() + "}";
JsonElement node = using(GSON_CONFIGURATION).parse(json).read("$.bd-property");
BigDecimal val = using(GSON_CONFIGURATION).parse(json).read("$.bd-property", BigDecimal.class);
assertThat(val).isEqualTo(bd);
assertThat(val).isEqualTo(node.getAsBigDecimal());
}
@Test
public void bigintegers_are_unwrapped() {
final BigInteger bi = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.TEN);
final String json = "{bi-property = " + bi.toString() + "}";
JsonElement node = using(GSON_CONFIGURATION).parse(json).read("$.bi-property");
BigInteger val = using(GSON_CONFIGURATION).parse(json).read("$.bi-property", BigInteger.class);
assertThat(val).isEqualTo(bi);
assertThat(val).isEqualTo(node.getAsBigInteger());
}
@Test
public void small_bigintegers_are_unwrapped() {
final BigInteger bi = BigInteger.valueOf(Long.MAX_VALUE);
final String json = "{bi-property = " + bi.toString() + "}";
JsonElement node = using(GSON_CONFIGURATION).parse(json).read("$.bi-property");
BigInteger val = using(GSON_CONFIGURATION).parse(json).read("$.bi-property", BigInteger.class);
assertThat(val).isEqualTo(bi);
assertThat(val).isEqualTo(node.getAsBigInteger());
}
@Test @Test
public void int_to_long_mapping() { public void int_to_long_mapping() {
assertThat(using(GSON_CONFIGURATION).parse("{\"val\": 1}").read("val", Long.class)).isEqualTo(1L); assertThat(using(GSON_CONFIGURATION).parse("{\"val\": 1}").read("val", Long.class)).isEqualTo(1L);

Loading…
Cancel
Save