From 017359cc3af20c996874049be88708be0f5d50b8 Mon Sep 17 00:00:00 2001 From: Ian Date: Fri, 11 Oct 2024 08:17:44 -0600 Subject: [PATCH 1/2] Allow number strings to be compared to numbers --- .../internal/filter/EvaluatorFactory.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) 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 322a1719..b2730557 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 @@ -102,6 +102,10 @@ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateCont 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.isStringNode() && right.isNumberNode()){ + return left.asStringNode().getString().compareTo(right.asNumberNode().getNumber().toString()) < 0; + } if(left.isNumberNode() && right.isStringNode()){ + return left.asNumberNode().getNumber().toString().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; } @@ -116,6 +120,10 @@ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateCont 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.isStringNode() && right.isNumberNode()){ + return left.asStringNode().getString().compareTo(right.asNumberNode().getNumber().toString()) <= 0; + } if(left.isNumberNode() && right.isStringNode()){ + return left.asNumberNode().getNumber().toString().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; } @@ -130,6 +138,10 @@ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateCont 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.isStringNode() && right.isNumberNode()){ + return left.asStringNode().getString().compareTo(right.asNumberNode().getNumber().toString()) > 0; + } else if (left.isNumberNode() && right.isStringNode()){ + return left.asNumberNode().getNumber().toString().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; } @@ -144,6 +156,10 @@ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateCont 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.isStringNode() && right.isNumberNode()){ + return left.asStringNode().getString().compareTo(right.asNumberNode().getNumber().toString()) >= 0; + } else if (left.isNumberNode() && right.isStringNode()){ + return left.asNumberNode().getNumber().toString().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; } From 55d21ab402115b635231e661c32baf16dc63da76 Mon Sep 17 00:00:00 2001 From: Ian Date: Thu, 17 Oct 2024 15:14:25 -0600 Subject: [PATCH 2/2] Change comparisons to handle number conversion and fallback to string comparison only when cast to number fails --- .../internal/filter/EvaluatorFactory.java | 93 +++++++++++++++---- 1 file changed, 73 insertions(+), 20 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 b2730557..652856b8 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 @@ -8,6 +8,8 @@ import java.util.Map; import java.util.regex.Pattern; +import java.math.BigDecimal; + import static com.jayway.jsonpath.internal.filter.ValueNodes.PatternNode; import static com.jayway.jsonpath.internal.filter.ValueNodes.ValueListNode; @@ -102,10 +104,23 @@ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateCont 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.isStringNode() && right.isNumberNode()){ - return left.asStringNode().getString().compareTo(right.asNumberNode().getNumber().toString()) < 0; - } if(left.isNumberNode() && right.isStringNode()){ - return left.asNumberNode().getNumber().toString().compareTo(right.asStringNode().getString()) < 0; + } if (left.isStringNode() && right.isNumberNode()) { + // Try to parse the string as a number for comparison + try { + BigDecimal leftAsNumber = new BigDecimal(left.asStringNode().getString()); + return leftAsNumber.compareTo(right.asNumberNode().getNumber()) < 0; + } catch (NumberFormatException e) { + return left.asStringNode().getString().compareTo(right.asNumberNode().getNumber().toString()) < 0; + } + } + if (left.isNumberNode() && right.isStringNode()) { + // Try to parse the string as a number for comparison + try { + BigDecimal rightAsNumber = new BigDecimal(right.asStringNode().getString()); + return left.asNumberNode().getNumber().compareTo(rightAsNumber) < 0; + } catch (NumberFormatException e) { + return left.asNumberNode().getNumber().toString().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; } @@ -120,10 +135,24 @@ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateCont 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.isStringNode() && right.isNumberNode()){ - return left.asStringNode().getString().compareTo(right.asNumberNode().getNumber().toString()) <= 0; - } if(left.isNumberNode() && right.isStringNode()){ - return left.asNumberNode().getNumber().toString().compareTo(right.asStringNode().getString()) <= 0; + } if (left.isStringNode() && right.isNumberNode()) { + // Try to parse the string as a number for comparison + try { + BigDecimal leftAsNumber = new BigDecimal(left.asStringNode().getString()); + return leftAsNumber.compareTo(right.asNumberNode().getNumber()) <= 0; + } catch (NumberFormatException e) { + // If parsing fails, fall back to string comparison + return left.asStringNode().getString().compareTo(right.asNumberNode().getNumber().toString()) <= 0; + } + } if (left.isNumberNode() && right.isStringNode()) { + // Try to parse the string as a number for comparison + try { + BigDecimal rightAsNumber = new BigDecimal(right.asStringNode().getString()); + return left.asNumberNode().getNumber().compareTo(rightAsNumber) <= 0; + } catch (NumberFormatException e) { + // If parsing fails, fall back to string comparison + return left.asNumberNode().getNumber().toString().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; } @@ -136,13 +165,25 @@ private static class GreaterThanEvaluator implements Evaluator { public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) { if(left.isNumberNode() && right.isNumberNode()){ return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) > 0; - } else if(left.isStringNode() && right.isStringNode()){ + } if(left.isStringNode() && right.isStringNode()){ return left.asStringNode().getString().compareTo(right.asStringNode().getString()) > 0; - } else if (left.isStringNode() && right.isNumberNode()){ - return left.asStringNode().getString().compareTo(right.asNumberNode().getNumber().toString()) > 0; - } else if (left.isNumberNode() && right.isStringNode()){ - return left.asNumberNode().getNumber().toString().compareTo(right.asStringNode().getString()) > 0; - } else if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613 + } if (left.isStringNode() && right.isNumberNode()) { + // Try to parse the string as a number for comparison + try { + BigDecimal leftAsNumber = new BigDecimal(left.asStringNode().getString()); + return leftAsNumber.compareTo(right.asNumberNode().getNumber()) > 0; + } catch (NumberFormatException e) { + return left.asStringNode().getString().compareTo(right.asNumberNode().getNumber().toString()) > 0; + } + } if (left.isNumberNode() && right.isStringNode()) { + // Try to parse the string as a number for comparison + try { + BigDecimal rightAsNumber = new BigDecimal(right.asStringNode().getString()); + return left.asNumberNode().getNumber().compareTo(rightAsNumber) > 0; + } catch (NumberFormatException e) { + return left.asNumberNode().getNumber().toString().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; @@ -154,13 +195,25 @@ private static class GreaterThanEqualsEvaluator implements Evaluator { public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) { if(left.isNumberNode() && right.isNumberNode()){ return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) >= 0; - } else if(left.isStringNode() && right.isStringNode()){ + } if(left.isStringNode() && right.isStringNode()){ return left.asStringNode().getString().compareTo(right.asStringNode().getString()) >= 0; - } else if (left.isStringNode() && right.isNumberNode()){ - return left.asStringNode().getString().compareTo(right.asNumberNode().getNumber().toString()) >= 0; - } else if (left.isNumberNode() && right.isStringNode()){ - return left.asNumberNode().getNumber().toString().compareTo(right.asStringNode().getString()) >= 0; - } else if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613 + } if (left.isStringNode() && right.isNumberNode()) { + // Try to parse the string as a number for comparison + try { + BigDecimal leftAsNumber = new BigDecimal(left.asStringNode().getString()); + return leftAsNumber.compareTo(right.asNumberNode().getNumber()) >= 0; + } catch (NumberFormatException e) { + return left.asStringNode().getString().compareTo(right.asNumberNode().getNumber().toString()) >= 0; + } + } if (left.isNumberNode() && right.isStringNode()) { + // Try to parse the string as a number for comparison + try { + BigDecimal rightAsNumber = new BigDecimal(right.asStringNode().getString()); + return left.asNumberNode().getNumber().compareTo(rightAsNumber) >= 0; + } catch (NumberFormatException e) { + return left.asNumberNode().getNumber().toString().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;