From 938e48f482d0f7b9df6a71ce0fb55a8e4639a760 Mon Sep 17 00:00:00 2001 From: Youngea <64700468+Youngea@users.noreply.github.com> Date: Wed, 5 May 2021 23:55:05 +0800 Subject: [PATCH] add feature for issue #613 and add testcases (#700) * add feature for issue #613 and add testcases * modification for asoffsetdatetime() function --- .../internal/filter/EvaluatorFactory.java | 8 +++ .../jsonpath/internal/filter/ValueNode.java | 26 ++++++- .../jsonpath/internal/filter/ValueNodes.java | 69 ++++++++++++++++--- .../java/com/jayway/jsonpath/issue_613.java | 40 +++++++++++ 4 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 json-path/src/test/java/com/jayway/jsonpath/issue_613.java 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 cfbfdff7..0ee59c72 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 @@ -100,6 +100,8 @@ public class EvaluatorFactory { return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) < 0; } if(left.isStringNode() && right.isStringNode()){ return left.asStringNode().getString().compareTo(right.asStringNode().getString()) < 0; + } if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613 + return left.asOffsetDateTimeNode().getDate().compareTo(right.asOffsetDateTimeNode().getDate()) < 0; } return false; } @@ -112,6 +114,8 @@ public class EvaluatorFactory { return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) <= 0; } if(left.isStringNode() && right.isStringNode()){ return left.asStringNode().getString().compareTo(right.asStringNode().getString()) <= 0; + } if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613 + return left.asOffsetDateTimeNode().getDate().compareTo(right.asOffsetDateTimeNode().getDate()) <= 0; } return false; } @@ -124,6 +128,8 @@ public class EvaluatorFactory { return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) > 0; } else if(left.isStringNode() && right.isStringNode()){ return left.asStringNode().getString().compareTo(right.asStringNode().getString()) > 0; + } else if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613 + return left.asOffsetDateTimeNode().getDate().compareTo(right.asOffsetDateTimeNode().getDate()) > 0; } return false; } @@ -136,6 +142,8 @@ public class EvaluatorFactory { return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) >= 0; } else if(left.isStringNode() && right.isStringNode()){ return left.asStringNode().getString().compareTo(right.asStringNode().getString()) >= 0; + } else if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613 + return left.asOffsetDateTimeNode().getDate().compareTo(right.asOffsetDateTimeNode().getDate()) >= 0; } return false; } 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 d87994ee..cdf0dd97 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 @@ -1,13 +1,15 @@ package com.jayway.jsonpath.internal.filter; -import java.util.regex.Pattern; - import com.jayway.jsonpath.InvalidPathException; import com.jayway.jsonpath.JsonPathException; import com.jayway.jsonpath.Predicate; import com.jayway.jsonpath.internal.Path; import com.jayway.jsonpath.internal.path.PathCompiler; import net.minidev.json.parser.JSONParser; + +import java.time.OffsetDateTime; +import java.util.regex.Pattern; + import static com.jayway.jsonpath.internal.filter.ValueNodes.*; public abstract class ValueNode { @@ -102,6 +104,16 @@ public abstract class ValueNode { throw new InvalidPathException("Expected class node"); } + //workaround for issue: https://github.com/json-path/JsonPath/issues/613 + public boolean isOffsetDateTimeNode(){ + return false; + } + + public OffsetDateTimeNode asOffsetDateTimeNode(){ + throw new InvalidPathException("Expected offsetDateTime node"); + } + + private static boolean isPath(Object o) { if(o == null || !(o instanceof String)){ return false; @@ -151,6 +163,7 @@ public abstract class ValueNode { // //---------------------------------------------------- public static ValueNode toValueNode(Object o){ + if(o == null) return NULL_NODE; if(o instanceof ValueNode) return (ValueNode)o; if(o instanceof Class) return createClassNode((Class)o); @@ -161,7 +174,9 @@ public abstract class ValueNode { else if(o instanceof Number) return createNumberNode(o.toString()); else if(o instanceof Boolean) return createBooleanNode(o.toString()); else if(o instanceof Pattern) return createPatternNode((Pattern)o); + else if (o instanceof OffsetDateTime) return createOffsetDateTimeNode(o.toString()); //workaround for issue: https://github.com/json-path/JsonPath/issues/613 else throw new JsonPathException("Could not determine value type"); + } public static StringNode createStringNode(CharSequence charSequence, boolean escape){ @@ -200,6 +215,12 @@ public abstract class ValueNode { return new PatternNode(pattern); } + //workaround for issue: https://github.com/json-path/JsonPath/issues/613 + public static OffsetDateTimeNode createOffsetDateTimeNode(CharSequence charSequence){ + return new OffsetDateTimeNode(charSequence); + } + + public static UndefinedNode createUndefinedNode() { return UNDEFINED; } @@ -212,5 +233,6 @@ public abstract class ValueNode { return new PathNode(path); } + } 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 c4030bc7..3f459a8c 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 @@ -1,12 +1,8 @@ package com.jayway.jsonpath.internal.filter; import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.time.OffsetDateTime; +import java.util.*; import java.util.regex.Pattern; import com.jayway.jsonpath.Configuration; @@ -333,6 +329,58 @@ public interface ValueNodes { } } + //workaround for issue: https://github.com/json-path/JsonPath/issues/613 + class OffsetDateTimeNode extends ValueNode { + + private final OffsetDateTime dateTime; + + + OffsetDateTimeNode(OffsetDateTime dateTime) { + this.dateTime = dateTime; + } + + OffsetDateTimeNode(CharSequence date) { + dateTime = OffsetDateTime.parse(date); + } + + @Override + public StringNode asStringNode() { + return new StringNode(dateTime.toString(), false); + } + + public OffsetDateTime getDate() { + return dateTime; + } + + @Override + public Class type(Predicate.PredicateContext ctx) { + return OffsetDateTimeNode.class; + } + + public boolean isOffsetDateTimeNode() { + return true; + } + + public OffsetDateTimeNode asOffsetDateTimeNode() { + return this; + } + + @Override + public String toString() { + return dateTime.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof OffsetDateTimeNode) && !(o instanceof StringNode)) return false; + OffsetDateTimeNode that = ((ValueNode)o).asOffsetDateTimeNode(); + return dateTime.compareTo(that.dateTime) == 0; + } + } + + + class BooleanNode extends ValueNode { private final Boolean value; @@ -373,6 +421,10 @@ public interface ValueNodes { } } + + + + class ClassNode extends ValueNode { private final Class clazz; @@ -646,16 +698,15 @@ public interface ValueNodes { if (res instanceof Number) return ValueNode.createNumberNode(res.toString()); else if (res instanceof String) return ValueNode.createStringNode(res.toString(), false); else if (res instanceof Boolean) return ValueNode.createBooleanNode(res.toString()); + else if (res instanceof OffsetDateTime) return ValueNode.createOffsetDateTimeNode(res.toString()); //workaround for issue: https://github.com/json-path/JsonPath/issues/613 else if (res == null) return NULL_NODE; else if (ctx.configuration().jsonProvider().isArray(res)) return ValueNode.createJsonNode(ctx.configuration().mappingProvider().map(res, List.class, ctx.configuration())); else if (ctx.configuration().jsonProvider().isMap(res)) return ValueNode.createJsonNode(ctx.configuration().mappingProvider().map(res, Map.class, ctx.configuration())); - else throw new JsonPathException("Could not convert " + res.toString() + " to a ValueNode"); + else throw new JsonPathException("Could not convert " + res.getClass().toString()+":"+ res.toString() + " to a ValueNode"); } catch (PathNotFoundException e) { return UNDEFINED; } } } - - } } diff --git a/json-path/src/test/java/com/jayway/jsonpath/issue_613.java b/json-path/src/test/java/com/jayway/jsonpath/issue_613.java new file mode 100644 index 00000000..b0966ca6 --- /dev/null +++ b/json-path/src/test/java/com/jayway/jsonpath/issue_613.java @@ -0,0 +1,40 @@ +package com.jayway.jsonpath; + +import org.junit.Test; + +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.LinkedHashMap; +import java.util.Map; + +import static com.jayway.jsonpath.Criteria.where; +import static com.jayway.jsonpath.Filter.filter; +import static org.assertj.core.api.Assertions.assertThat; + +//test for issue: https://github.com/json-path/JsonPath/issues/613 +public class issue_613 extends BaseTest{ + final OffsetDateTime ofdt_small = OffsetDateTime.of(1999,2,1,1,1,1,1, ZoneOffset.UTC); + final OffsetDateTime ofdt_middle = OffsetDateTime.of(2000,2,1,1,1,1,1, ZoneOffset.UTC); + final OffsetDateTime ofdt_big = OffsetDateTime.of(2001,3,1,1,1,1,1, ZoneOffset.MAX); + + Map map_middle = new LinkedHashMap(){ + { + put("time",ofdt_middle); + }}; + + @Test + public void issue_613_eq_ne_test() { + assertThat(filter(where("time").eq(ofdt_middle)).apply(createPredicateContext(map_middle))).isEqualTo(true); + assertThat(filter(where("time").ne(ofdt_big)).apply(createPredicateContext(map_middle))).isEqualTo(true); + } + @Test + public void issue_613_lt_lte_test() { + assertThat(filter(where("time").lt(ofdt_big)).apply(createPredicateContext(map_middle))).isEqualTo(true); + assertThat(filter(where("time").lte(ofdt_small)).apply(createPredicateContext(map_middle))).isEqualTo(false); + } + @Test + public void issue_613_gt_gte_test() { + assertThat(filter(where("time").gt(ofdt_big)).apply(createPredicateContext(map_middle))).isEqualTo(false); + assertThat(filter(where("time").gte(ofdt_small)).apply(createPredicateContext(map_middle))).isEqualTo(true); + } +}