Skip to content

Commit

Permalink
Not using exceptions for flow control (#775)
Browse files Browse the repository at this point in the history
  • Loading branch information
r0goyal committed Dec 22, 2021
1 parent 39c7904 commit b14341a
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 76 deletions.
155 changes: 88 additions & 67 deletions json-path/src/main/java/com/jayway/jsonpath/JsonPath.java
Expand Up @@ -24,8 +24,6 @@
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;
Expand Down Expand Up @@ -171,40 +169,41 @@ public <T> T read(Object jsonObject, Configuration configuration) {
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;
}
}
}

Expand All @@ -220,6 +219,14 @@ public <T> T set(Object jsonObject, Object newVal, Configuration configuration)
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);
}
Expand All @@ -239,30 +246,19 @@ public <T> T map(Object jsonObject, MapFunction mapFunction, Configuration confi
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);

}

Expand All @@ -277,24 +273,19 @@ public <T> T map(Object jsonObject, MapFunction mapFunction, Configuration confi
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);
}

/**
Expand All @@ -310,6 +301,14 @@ public <T> T add(Object jsonObject, Object value, Configuration configuration) {
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);
}
Expand All @@ -320,7 +319,7 @@ public <T> T add(Object jsonObject, Object value, Configuration configuration) {
* 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
Expand All @@ -331,6 +330,14 @@ public <T> T put(Object jsonObject, String key, Object value, Configuration conf
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);
}
Expand Down Expand Up @@ -737,4 +744,18 @@ private <T> T resultByConfiguration(Object jsonObject, Configuration configurati
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());
}
}
}
}
Expand Up @@ -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;

Expand All @@ -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));
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -54,7 +55,7 @@ public boolean multiPropertyMergeCase() {

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
Expand All @@ -63,14 +64,14 @@ public void evaluate(String currentPath, PathRef parent, Object model, Evaluatio
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()));
}
}
Expand Down

0 comments on commit b14341a

Please sign in to comment.