Browse Source

Not using exceptions for flow control (#775)

pull/781/head
Rishabh 3 years ago committed by GitHub
parent
commit
b14341ac5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 155
      json-path/src/main/java/com/jayway/jsonpath/JsonPath.java
  2. 10
      json-path/src/main/java/com/jayway/jsonpath/internal/path/ArrayPathToken.java
  3. 9
      json-path/src/main/java/com/jayway/jsonpath/internal/path/PropertyPathToken.java

155
json-path/src/main/java/com/jayway/jsonpath/JsonPath.java

@ -24,8 +24,6 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import static com.jayway.jsonpath.Option.ALWAYS_RETURN_LIST;
import static com.jayway.jsonpath.Option.AS_PATH_LIST;
@ -171,40 +169,41 @@ public class JsonPath {
boolean optAlwaysReturnList = configuration.containsOption(Option.ALWAYS_RETURN_LIST);
boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);
try {
if (path.isFunctionPath()) {
if (optAsPathList || optAlwaysReturnList) {
throw new JsonPathException("Options " + AS_PATH_LIST + " and " + ALWAYS_RETURN_LIST + " are not allowed when using path functions!");
}
return path.evaluate(jsonObject, jsonObject, configuration).getValue(true);
} else if (optAsPathList) {
return (T) path.evaluate(jsonObject, jsonObject, configuration).getPath();
} else {
Object res = path.evaluate(jsonObject, jsonObject, configuration).getValue(false);
if (optAlwaysReturnList && path.isDefinite()) {
Object array = configuration.jsonProvider().createArray();
configuration.jsonProvider().setArrayIndex(array, 0, res);
return (T) array;
} else {
return (T) res;
if (path.isFunctionPath()) {
if (optAsPathList || optAlwaysReturnList) {
if (optSuppressExceptions) {
return (T) (path.isDefinite() ? null : configuration.jsonProvider().createArray());
}
throw new JsonPathException("Options " + AS_PATH_LIST + " and " + ALWAYS_RETURN_LIST + " are not allowed when using path functions!");
}
} catch (RuntimeException e) {
if (!optSuppressExceptions) {
throw e;
} else {
if (optAsPathList) {
EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration);
if (optSuppressExceptions && evaluationContext.getPathList().isEmpty()) {
return (T) (path.isDefinite() ? null : configuration.jsonProvider().createArray());
}
return evaluationContext.getValue(true);
} else if (optAsPathList) {
EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration);
if (optSuppressExceptions && evaluationContext.getPathList().isEmpty()) {
return (T) configuration.jsonProvider().createArray();
}
return (T) evaluationContext.getPath();
} else {
EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration);
if (optSuppressExceptions && evaluationContext.getPathList().isEmpty()) {
if (optAlwaysReturnList) {
return (T) configuration.jsonProvider().createArray();
} else {
if (optAlwaysReturnList) {
return (T) configuration.jsonProvider().createArray();
} else {
return (T) (path.isDefinite() ? null : configuration.jsonProvider().createArray());
}
return (T) (path.isDefinite() ? null : configuration.jsonProvider().createArray());
}
}
Object res = evaluationContext.getValue(false);
if (optAlwaysReturnList && path.isDefinite()) {
Object array = configuration.jsonProvider().createArray();
configuration.jsonProvider().setArrayIndex(array, 0, res);
return (T) array;
} else {
return (T) res;
}
}
}
@ -220,6 +219,14 @@ public class JsonPath {
notNull(jsonObject, "json can not be null");
notNull(configuration, "configuration can not be null");
EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration, true);
if (evaluationContext.getPathList().isEmpty()) {
boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);
if (optSuppressExceptions) {
return handleMissingPathInContext(configuration);
} else {
throw new PathNotFoundException();
}
}
for (PathRef updateOperation : evaluationContext.updateOperations()) {
updateOperation.set(newVal, configuration);
}
@ -239,30 +246,19 @@ public class JsonPath {
notNull(jsonObject, "json can not be null");
notNull(configuration, "configuration can not be null");
notNull(mapFunction, "mapFunction can not be null");
boolean optAsPathList = configuration.containsOption(AS_PATH_LIST);
boolean optAlwaysReturnList = configuration.containsOption(Option.ALWAYS_RETURN_LIST);
boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);
try {
EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration, true);
for (PathRef updateOperation : evaluationContext.updateOperations()) {
updateOperation.convert(mapFunction, configuration);
}
return resultByConfiguration(jsonObject, configuration, evaluationContext);
}catch (RuntimeException e) {
if (!optSuppressExceptions) {
throw e;
EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration, true);
if (evaluationContext.getPathList().isEmpty()) {
boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);
if (optSuppressExceptions) {
return handleMissingPathInContext(configuration);
} else {
if (optAsPathList) {
return (T) configuration.jsonProvider().createArray();
} else {
if (optAlwaysReturnList) {
return (T) configuration.jsonProvider().createArray();
} else {
return (T) (path.isDefinite() ? null : configuration.jsonProvider().createArray());
}
}
throw new PathNotFoundException();
}
}
for (PathRef updateOperation : evaluationContext.updateOperations()) {
updateOperation.convert(mapFunction, configuration);
}
return resultByConfiguration(jsonObject, configuration, evaluationContext);
}
@ -277,24 +273,19 @@ public class JsonPath {
public <T> T delete(Object jsonObject, Configuration configuration) {
notNull(jsonObject, "json can not be null");
notNull(configuration, "configuration can not be null");
boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);
try {
EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration, true);
for (PathRef updateOperation : evaluationContext.updateOperations()) {
updateOperation.delete(configuration);
}
return resultByConfiguration(jsonObject, configuration, evaluationContext);
} catch (RuntimeException e) {
if (!optSuppressExceptions) {
throw e;
EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration, true);
if (evaluationContext.getPathList().isEmpty()) {
boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);
if (optSuppressExceptions) {
return handleMissingPathInContext(configuration);
} else {
List<String> list = new ArrayList<String>(); // the log messages
list.add("delete throws "+e.getMessage()); // TODO
return (T) list;
throw new PathNotFoundException();
}
}
for (PathRef updateOperation : evaluationContext.updateOperations()) {
updateOperation.delete(configuration);
}
return resultByConfiguration(jsonObject, configuration, evaluationContext);
}
/**
@ -310,6 +301,14 @@ public class JsonPath {
notNull(jsonObject, "json can not be null");
notNull(configuration, "configuration can not be null");
EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration, true);
if (evaluationContext.getPathList().isEmpty()) {
boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);
if (optSuppressExceptions) {
return handleMissingPathInContext(configuration);
} else {
throw new PathNotFoundException();
}
}
for (PathRef updateOperation : evaluationContext.updateOperations()) {
updateOperation.add(value, configuration);
}
@ -320,7 +319,7 @@ public class JsonPath {
* Adds or updates the Object this path points to in the provided jsonObject with a key with a value
*
* @param jsonObject a json object
* @param key the key to add or update
* @param key the key to add or update
* @param value the new value
* @param configuration configuration to use
* @param <T> expected return type
@ -331,6 +330,14 @@ public class JsonPath {
notEmpty(key, "key can not be null or empty");
notNull(configuration, "configuration can not be null");
EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration, true);
if (evaluationContext.getPathList().isEmpty()) {
boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);
if (optSuppressExceptions) {
return handleMissingPathInContext(configuration);
} else {
throw new PathNotFoundException();
}
}
for (PathRef updateOperation : evaluationContext.updateOperations()) {
updateOperation.put(key, value, configuration);
}
@ -737,4 +744,18 @@ public class JsonPath {
return (T) jsonObject;
}
}
private <T> T handleMissingPathInContext(final Configuration configuration) {
boolean optAsPathList = configuration.containsOption(AS_PATH_LIST);
boolean optAlwaysReturnList = configuration.containsOption(Option.ALWAYS_RETURN_LIST);
if (optAsPathList) {
return (T) configuration.jsonProvider().createArray();
} else {
if (optAlwaysReturnList) {
return (T) configuration.jsonProvider().createArray();
} else {
return (T) (path.isDefinite() ? null : configuration.jsonProvider().createArray());
}
}
}
}

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

@ -15,10 +15,8 @@
package com.jayway.jsonpath.internal.path;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.PathRef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static java.lang.String.format;
@ -35,14 +33,16 @@ public abstract class ArrayPathToken extends PathToken {
*/
protected boolean checkArrayModel(String currentPath, Object model, EvaluationContextImpl ctx) {
if (model == null){
if (! isUpstreamDefinite()) {
if (!isUpstreamDefinite()
|| ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)) {
return false;
} else {
throw new PathNotFoundException("The path " + currentPath + " is null");
}
}
if (!ctx.jsonProvider().isArray(model)) {
if (! isUpstreamDefinite()) {
if (!isUpstreamDefinite()
|| ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)) {
return false;
} else {
throw new PathNotFoundException(format("Filter: %s can only be applied to arrays. Current context is: %s", toString(), model));

9
json-path/src/main/java/com/jayway/jsonpath/internal/path/PropertyPathToken.java

@ -15,6 +15,7 @@
package com.jayway.jsonpath.internal.path;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.internal.Utils;
@ -54,7 +55,7 @@ class PropertyPathToken extends PathToken {
public boolean multiPropertyIterationCase() {
// Semantics of this case is the same as semantics of ArrayPathToken with INDEX_SEQUENCE operation.
return ! isLeaf() && properties.size() > 1;
return !isLeaf() && properties.size() > 1;
}
@Override
@ -63,14 +64,14 @@ class PropertyPathToken extends PathToken {
assert onlyOneIsTrueNonThrow(singlePropertyCase(), multiPropertyMergeCase(), multiPropertyIterationCase());
if (!ctx.jsonProvider().isMap(model)) {
if (! isUpstreamDefinite()) {
if (!isUpstreamDefinite()
|| ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)) {
return;
} else {
String m = model == null ? "null" : model.getClass().getName();
throw new PathNotFoundException(String.format(
"Expected to find an object with property %s in path %s but found '%s'. " +
"This is not a json object according to the JsonProvider: '%s'.",
"This is not a json object according to the JsonProvider: '%s'.",
getPathFragment(), currentPath, m, ctx.configuration().jsonProvider().getClass().getName()));
}
}

Loading…
Cancel
Save