From 829469d8498110c389385cddc82c1b5373af22f7 Mon Sep 17 00:00:00 2001 From: LiYichen99 <771515150@qq.com> Date: Fri, 27 May 2022 21:21:39 +0800 Subject: [PATCH] fix Issue_356 --- .../internal/filter/EvaluatorFactory.java | 47 +++----- .../jsonpath/internal/filter/ValueNode.java | 10 ++ .../jsonpath/internal/filter/ValueNodes.java | 61 ++++++++++ .../java/com/jayway/jsonpath/Issue_356.java | 110 ++++++++++-------- 4 files changed, 149 insertions(+), 79 deletions(-) diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java index 27ef1c8c..1ce052da 100755 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java +++ b/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 { + /** + * Evaluate the match operation of predicate. + * + * @param left the ValueNode + * @param right the ValueNode + * @param ctx the PredicateContext + * @return boolean + */ @Override - public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) { - Predicate.PredicateContext predicateContext = new PredicateContextImpl( - getNodeValue(left), + public boolean evaluate(final ValueNode left, final ValueNode right, final Predicate.PredicateContext ctx) { + // CS304 Issue link: https://github.com/json-path/JsonPath/issues/356 + // Create new predicateContext according to the left ValueNode + final Predicate.PredicateContext predicateContext = new PredicateContextImpl( + left.getValue(), ctx.root(), ctx.configuration(), null ); - return right.asPredicateNode().getPredicate().apply(predicateContext); - } - - 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; + return right.asPredicateNode().getPredicate().apply(predicateContext); //NOPMD - suppressed LawOfDemeter //NOPMD - suppressed LawOfDemeter } } diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java index cdf0dd97..b9ed24e8 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java +++ b/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); + /** + * 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() { return false; } @@ -157,6 +166,7 @@ public abstract class ValueNode { + //---------------------------------------------------- // // Factory methods diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java index 3f459a8c..07c25325 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java @@ -71,6 +71,11 @@ public interface ValueNodes { return Void.TYPE; } + @Override + public Object getValue() { + return compiledPattern; + } + public boolean isPatternNode() { return true; } @@ -125,6 +130,11 @@ public interface ValueNodes { else return Void.class; } + @Override + public Object getValue() { + return json; + } + public boolean isJsonNode() { return true; } @@ -248,6 +258,11 @@ public interface ValueNodes { return String.class; } + @Override + public Object getValue() { + return string; + } + public boolean isStringNode() { return true; } @@ -301,6 +316,11 @@ public interface ValueNodes { return Number.class; } + @Override + public Object getValue() { + return number; + } + public boolean isNumberNode() { return true; } @@ -357,6 +377,11 @@ public interface ValueNodes { return OffsetDateTimeNode.class; } + @Override + public Object getValue() { + return dateTime; + } + public boolean isOffsetDateTimeNode() { return true; } @@ -393,6 +418,11 @@ public interface ValueNodes { return Boolean.class; } + @Override + public Object getValue() { + return value; + } + public boolean isBooleanNode() { return true; } @@ -437,6 +467,11 @@ public interface ValueNodes { return Class.class; } + @Override + public Object getValue() { + return clazz; + } + public boolean isClassNode() { return true; } @@ -474,6 +509,11 @@ public interface ValueNodes { return Void.class; } + @Override + public Object getValue() { + return null; + } + @Override public boolean isNullNode() { return true; @@ -505,6 +545,11 @@ public interface ValueNodes { return Void.class; } + @Override + public Object getValue() { + return null; + } + public UndefinedNode asUndefinedNode() { return this; } @@ -540,6 +585,11 @@ public interface ValueNodes { return Void.class; } + @Override + public Object getValue() { + return predicate; + } + public boolean isPredicateNode() { return true; } @@ -587,6 +637,12 @@ public interface ValueNodes { return List.class; } + @Override + public Object getValue() { + List valueNodes = new ArrayList<>(nodes); + return valueNodes; + } + public boolean isValueListNode() { return true; } @@ -656,6 +712,11 @@ public interface ValueNodes { return Void.class; } + @Override + public Object getValue() { + return path; + } + public boolean isPathNode() { return true; } diff --git a/json-path/src/test/java/com/jayway/jsonpath/Issue_356.java b/json-path/src/test/java/com/jayway/jsonpath/Issue_356.java index 004f3262..8601dfcf 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/Issue_356.java +++ b/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; import org.junit.Test; @@ -6,68 +8,84 @@ import java.math.BigDecimal; import java.util.LinkedHashMap; import static com.jayway.jsonpath.Criteria.where; +import static org.assertj.core.api.Assertions.assertThat; /** * Test for issue 356 */ -public class Issue_356 { - private final static String json = "{\n" + - " \"store\": {\n" + - " \"book\": [\n" + - " {\n" + - " \"title\": \"Sayings of the Century\",\n" + - " \"price\": {\n" + - " \"value\": 8.95,\n" + - " \"currency\": \"usd\"\n" + - " }\n" + - " },\n" + - " {\n" + - " \"title\": \"Sword of Honour\",\n" + - " \"price\": {\n" + - " \"value\": 12.99,\n" + - " \"currency\": \"usd\"\n" + - " }\n" + - " },\n" + - " {\n" + - " \"title\": \"Moby Dick\",\n" + - " \"price\": {\n" + - " \"value\": 8.99,\n" + - " \"currency\": \"usd\"\n" + - " }\n" + - " }\n" + - " ]\n" + - " }\n" + - "}"; +public class Issue_356 { //NOPMD - suppressed AtLeastOneConstructor //NOPMD - suppressed ClassNamingConventions + /** + * The json data for testing + */ + private static final String JSON = "{\n" + + " \"store\": {\n" + + " \"book\": [\n" + + " {\n" + + " \"title\": \"Sayings of the Century\",\n" + + " \"price\": {\n" + + " \"value\": 8.95,\n" + + " \"currency\": \"usd\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"title\": \"Sword of Honour\",\n" + + " \"price\": {\n" + + " \"value\": 12.99,\n" + + " \"currency\": \"usd\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"title\": \"Moby Dick\",\n" + + " \"price\": {\n" + + " \"value\": 8.99,\n" + + " \"currency\": \"usd\"\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 - public void test1(){ - Object ans = JsonPath.parse(json).read("$..book[?]", Filter.filter(where("price.value").matches(new Predicate() { + public void test1() { + final Object ans = JsonPath.parse(JSON).read("$..book[?]", Filter.filter(where("price.value").matches(new Predicate() { //NOPMD - suppressed DataflowAnomalyAnalysis @Override - public boolean apply(PredicateContext ctx) { + public boolean apply(final PredicateContext ctx) { // 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); - assert(ans.toString().equals("[{\"title\":\"Sayings of the Century\"," + - "\"price\":{\"value\":8.95,\"currency\":\"usd\"}}," + - "{\"title\":\"Moby Dick\"," + - "\"price\":{\"value\":8.99,\"currency\":\"usd\"}}]")); + assertThat(ans.toString().equals("[{\"title\":\"Sayings of the Century\"," //NOPMD - suppressed LawOfDemeter + + "\"price\":{\"value\":8.95,\"currency\":\"usd\"}}," + + "{\"title\":\"Moby Dick\"," + + "\"price\":{\"value\":8.99,\"currency\":\"usd\"}}]")).isTrue(); } + + /** + * test2 for "...price" PredicateContext, + * it will return the book with the price value less than 9 + */ @Test - public void test2(){ - Object ans = JsonPath.parse(json).read("$..book[?]", Filter.filter(where("price").matches(new Predicate() { + public void test2() { + final Object ans = JsonPath.parse(JSON).read("$..book[?]", Filter.filter(where("price").matches(new Predicate() { //NOPMD - suppressed DataflowAnomalyAnalysis @Override - public boolean apply(PredicateContext ctx) { + public boolean apply(final PredicateContext ctx) { //NOPMD - suppressed CommentRequired // some custom logic with expecting value number in context - return ((LinkedHashMap) ctx.item()).get("value") < 9; + return ((LinkedHashMap) ctx.item()).get("value") < CONSTRAINT; } }))); - // System.out.println(ans); - assert(ans.toString().equals("[{\"title\":\"Sayings of the Century\"," + - "\"price\":{\"value\":8.95,\"currency\":\"usd\"}}," + - "{\"title\":\"Moby Dick\"," + - "\"price\":{\"value\":8.99,\"currency\":\"usd\"}}]")); + assertThat(ans.toString().equals("[{\"title\":\"Sayings of the Century\"," //NOPMD - suppressed LawOfDemeter + + "\"price\":{\"value\":8.95,\"currency\":\"usd\"}}," + + "{\"title\":\"Moby Dick\"," + + "\"price\":{\"value\":8.99,\"currency\":\"usd\"}}]")).isTrue(); } }