Browse Source

fix Issue_356

pull/839/head
LiYichen99 3 years ago
parent
commit
829469d849
  1. 47
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java
  2. 10
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java
  3. 61
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java
  4. 110
      json-path/src/test/java/com/jayway/jsonpath/Issue_356.java

47
json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java

@ -245,44 +245,25 @@ public class EvaluatorFactory {
} }
private static class PredicateMatchEvaluator implements Evaluator { private static class PredicateMatchEvaluator implements Evaluator {
/**
* Evaluate the match operation of predicate.
*
* @param left the ValueNode
* @param right the ValueNode
* @param ctx the PredicateContext
* @return boolean
*/
@Override @Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) { public boolean evaluate(final ValueNode left, final ValueNode right, final Predicate.PredicateContext ctx) {
Predicate.PredicateContext predicateContext = new PredicateContextImpl( // CS304 Issue link: https://github.com/json-path/JsonPath/issues/356
getNodeValue(left), // Create new predicateContext according to the left ValueNode
final Predicate.PredicateContext predicateContext = new PredicateContextImpl(
left.getValue(),
ctx.root(), ctx.root(),
ctx.configuration(), ctx.configuration(),
null null
); );
return right.asPredicateNode().getPredicate().apply(predicateContext); return right.asPredicateNode().getPredicate().apply(predicateContext); //NOPMD - suppressed LawOfDemeter //NOPMD - suppressed LawOfDemeter
}
public Object getNodeValue(ValueNode node) {
if(node.isPatternNode()){
return ((ValueNodes.PatternNode) node).getCompiledPattern();
} else if(node.isPathNode()){
return ((ValueNodes.PathNode) node).getPath();
} else if(node.isNumberNode()){
return ((ValueNodes.NumberNode) node).getNumber();
} else if(node.isStringNode()){
return ((ValueNodes.StringNode) node).getString();
} else if(node.isBooleanNode()){
return ((ValueNodes.BooleanNode) node).getBoolean();
} else if(node.isJsonNode()){
return ((ValueNodes.JsonNode) node).getJson();
} else if(node.isPredicateNode()){
return ((ValueNodes.PredicateNode) node).getPredicate();
} else if(node.isValueListNode()){
return ((ValueNodes.ValueListNode) node).getNodes();
} else if(node.isNullNode()){
return node.toString();
} else if(node.isUndefinedNode()){
return "undefined";
} else if(node.isClassNode()){
return ((ValueNodes.ClassNode) node).getClazz();
} else if(node.isOffsetDateTimeNode()){
return ((ValueNodes.OffsetDateTimeNode) node).getDate();
}
return null;
} }
} }

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

@ -16,6 +16,15 @@ public abstract class ValueNode {
public abstract Class<?> type(Predicate.PredicateContext ctx); public abstract Class<?> type(Predicate.PredicateContext ctx);
/**
* Get the value of ValueNode.
* The class of return Object depends on the type of ValueNode.
*
* @return Object
*/
// CS304 Issue link: https://github.com/json-path/JsonPath/issues/356
public abstract Object getValue();
public boolean isPatternNode() { public boolean isPatternNode() {
return false; return false;
} }
@ -157,6 +166,7 @@ public abstract class ValueNode {
//---------------------------------------------------- //----------------------------------------------------
// //
// Factory methods // Factory methods

61
json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java

@ -71,6 +71,11 @@ public interface ValueNodes {
return Void.TYPE; return Void.TYPE;
} }
@Override
public Object getValue() {
return compiledPattern;
}
public boolean isPatternNode() { public boolean isPatternNode() {
return true; return true;
} }
@ -125,6 +130,11 @@ public interface ValueNodes {
else return Void.class; else return Void.class;
} }
@Override
public Object getValue() {
return json;
}
public boolean isJsonNode() { public boolean isJsonNode() {
return true; return true;
} }
@ -248,6 +258,11 @@ public interface ValueNodes {
return String.class; return String.class;
} }
@Override
public Object getValue() {
return string;
}
public boolean isStringNode() { public boolean isStringNode() {
return true; return true;
} }
@ -301,6 +316,11 @@ public interface ValueNodes {
return Number.class; return Number.class;
} }
@Override
public Object getValue() {
return number;
}
public boolean isNumberNode() { public boolean isNumberNode() {
return true; return true;
} }
@ -357,6 +377,11 @@ public interface ValueNodes {
return OffsetDateTimeNode.class; return OffsetDateTimeNode.class;
} }
@Override
public Object getValue() {
return dateTime;
}
public boolean isOffsetDateTimeNode() { public boolean isOffsetDateTimeNode() {
return true; return true;
} }
@ -393,6 +418,11 @@ public interface ValueNodes {
return Boolean.class; return Boolean.class;
} }
@Override
public Object getValue() {
return value;
}
public boolean isBooleanNode() { public boolean isBooleanNode() {
return true; return true;
} }
@ -437,6 +467,11 @@ public interface ValueNodes {
return Class.class; return Class.class;
} }
@Override
public Object getValue() {
return clazz;
}
public boolean isClassNode() { public boolean isClassNode() {
return true; return true;
} }
@ -474,6 +509,11 @@ public interface ValueNodes {
return Void.class; return Void.class;
} }
@Override
public Object getValue() {
return null;
}
@Override @Override
public boolean isNullNode() { public boolean isNullNode() {
return true; return true;
@ -505,6 +545,11 @@ public interface ValueNodes {
return Void.class; return Void.class;
} }
@Override
public Object getValue() {
return null;
}
public UndefinedNode asUndefinedNode() { public UndefinedNode asUndefinedNode() {
return this; return this;
} }
@ -540,6 +585,11 @@ public interface ValueNodes {
return Void.class; return Void.class;
} }
@Override
public Object getValue() {
return predicate;
}
public boolean isPredicateNode() { public boolean isPredicateNode() {
return true; return true;
} }
@ -587,6 +637,12 @@ public interface ValueNodes {
return List.class; return List.class;
} }
@Override
public Object getValue() {
List<ValueNode> valueNodes = new ArrayList<>(nodes);
return valueNodes;
}
public boolean isValueListNode() { public boolean isValueListNode() {
return true; return true;
} }
@ -656,6 +712,11 @@ public interface ValueNodes {
return Void.class; return Void.class;
} }
@Override
public Object getValue() {
return path;
}
public boolean isPathNode() { public boolean isPathNode() {
return true; return true;
} }

110
json-path/src/test/java/com/jayway/jsonpath/Issue_356.java

@ -1,3 +1,5 @@
// CS304 (manually written)
// Issue link: https://github.com/json-path/JsonPath/issues/356
package com.jayway.jsonpath; package com.jayway.jsonpath;
import org.junit.Test; import org.junit.Test;
@ -6,68 +8,84 @@ import java.math.BigDecimal;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import static com.jayway.jsonpath.Criteria.where; import static com.jayway.jsonpath.Criteria.where;
import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Test for issue 356 * Test for issue 356
*/ */
public class Issue_356 { public class Issue_356 { //NOPMD - suppressed AtLeastOneConstructor //NOPMD - suppressed ClassNamingConventions
private final static String json = "{\n" + /**
" \"store\": {\n" + * The json data for testing
" \"book\": [\n" + */
" {\n" + private static final String JSON = "{\n"
" \"title\": \"Sayings of the Century\",\n" + + " \"store\": {\n"
" \"price\": {\n" + + " \"book\": [\n"
" \"value\": 8.95,\n" + + " {\n"
" \"currency\": \"usd\"\n" + + " \"title\": \"Sayings of the Century\",\n"
" }\n" + + " \"price\": {\n"
" },\n" + + " \"value\": 8.95,\n"
" {\n" + + " \"currency\": \"usd\"\n"
" \"title\": \"Sword of Honour\",\n" + + " }\n"
" \"price\": {\n" + + " },\n"
" \"value\": 12.99,\n" + + " {\n"
" \"currency\": \"usd\"\n" + + " \"title\": \"Sword of Honour\",\n"
" }\n" + + " \"price\": {\n"
" },\n" + + " \"value\": 12.99,\n"
" {\n" + + " \"currency\": \"usd\"\n"
" \"title\": \"Moby Dick\",\n" + + " }\n"
" \"price\": {\n" + + " },\n"
" \"value\": 8.99,\n" + + " {\n"
" \"currency\": \"usd\"\n" + + " \"title\": \"Moby Dick\",\n"
" }\n" + + " \"price\": {\n"
" }\n" + + " \"value\": 8.99,\n"
" ]\n" + + " \"currency\": \"usd\"\n"
" }\n" + + " }\n"
"}"; + " }\n"
+ " ]\n"
+ " }\n"
+ "}";
/**
* The constraint for testing
*/
private static final double CONSTRAINT = 9;
/**
* test1 for "...price.value" PredicateContext,
* it will return the book with the price value less than 9
*/
@Test @Test
public void test1(){ public void test1() {
Object ans = JsonPath.parse(json).read("$..book[?]", Filter.filter(where("price.value").matches(new Predicate() { final Object ans = JsonPath.parse(JSON).read("$..book[?]", Filter.filter(where("price.value").matches(new Predicate() { //NOPMD - suppressed DataflowAnomalyAnalysis
@Override @Override
public boolean apply(PredicateContext ctx) { public boolean apply(final PredicateContext ctx) {
// some custom logic with expecting value number in context // some custom logic with expecting value number in context
return ((BigDecimal)ctx.item()).doubleValue() < 9; return ((BigDecimal) ctx.item()).doubleValue() < CONSTRAINT;
} }
}))); })));
// System.out.println(ans); assertThat(ans.toString().equals("[{\"title\":\"Sayings of the Century\"," //NOPMD - suppressed LawOfDemeter
assert(ans.toString().equals("[{\"title\":\"Sayings of the Century\"," + + "\"price\":{\"value\":8.95,\"currency\":\"usd\"}},"
"\"price\":{\"value\":8.95,\"currency\":\"usd\"}}," + + "{\"title\":\"Moby Dick\","
"{\"title\":\"Moby Dick\"," + + "\"price\":{\"value\":8.99,\"currency\":\"usd\"}}]")).isTrue();
"\"price\":{\"value\":8.99,\"currency\":\"usd\"}}]"));
} }
/**
* test2 for "...price" PredicateContext,
* it will return the book with the price value less than 9
*/
@Test @Test
public void test2(){ public void test2() {
Object ans = JsonPath.parse(json).read("$..book[?]", Filter.filter(where("price").matches(new Predicate() { final Object ans = JsonPath.parse(JSON).read("$..book[?]", Filter.filter(where("price").matches(new Predicate() { //NOPMD - suppressed DataflowAnomalyAnalysis
@Override @Override
public boolean apply(PredicateContext ctx) { public boolean apply(final PredicateContext ctx) { //NOPMD - suppressed CommentRequired
// some custom logic with expecting value number in context // some custom logic with expecting value number in context
return ((LinkedHashMap<String, Double>) ctx.item()).get("value") < 9; return ((LinkedHashMap<String, Double>) ctx.item()).get("value") < CONSTRAINT;
} }
}))); })));
// System.out.println(ans); assertThat(ans.toString().equals("[{\"title\":\"Sayings of the Century\"," //NOPMD - suppressed LawOfDemeter
assert(ans.toString().equals("[{\"title\":\"Sayings of the Century\"," + + "\"price\":{\"value\":8.95,\"currency\":\"usd\"}},"
"\"price\":{\"value\":8.95,\"currency\":\"usd\"}}," + + "{\"title\":\"Moby Dick\","
"{\"title\":\"Moby Dick\"," + + "\"price\":{\"value\":8.99,\"currency\":\"usd\"}}]")).isTrue();
"\"price\":{\"value\":8.99,\"currency\":\"usd\"}}]"));
} }
} }

Loading…
Cancel
Save