Browse Source

Merge 233c2f40a7 into 2cfcf3c22a

pull/297/merge
Space 8 years ago committed by GitHub
parent
commit
debe7c5fd4
  1. 7
      json-path/src/main/java/com/jayway/jsonpath/Option.java
  2. 7
      json-path/src/main/java/com/jayway/jsonpath/Predicate.java
  3. 268
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/DefaultEvaluatorFactory.java
  4. 270
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java
  5. 60
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ImplicitNumericConversionEvaluatorFactory.java
  6. 5
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/RelationalExpressionNode.java
  7. 27
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/RelationalOperator.java
  8. 10
      json-path/src/main/java/com/jayway/jsonpath/internal/path/PredicateContextImpl.java
  9. 5
      json-path/src/test/java/com/jayway/jsonpath/BaseTest.java
  10. 349
      json-path/src/test/java/com/jayway/jsonpath/FilterTest.java
  11. 2
      json-path/src/test/java/com/jayway/jsonpath/internal/filter/RegexpEvaluatorTest.java
  12. 7
      json-path/src/test/java/com/jayway/jsonpath/old/IssuesTest.java

7
json-path/src/main/java/com/jayway/jsonpath/Option.java

@ -83,6 +83,11 @@ public enum Option {
* If REQUIRE_PROPERTIES option is present PathNotFoundException is thrown.
* If REQUIRE_PROPERTIES option is not present ["b-val"] is returned.
*/
REQUIRE_PROPERTIES
REQUIRE_PROPERTIES,
/**
* Configures JsonPath to implicitly convert strings to numbers for comparisons in filters,
* mimicking behavior in javascript, e.g. 9 < "73"
*/
IMPLICIT_NUMERIC_CONVERSIONS
}

7
json-path/src/main/java/com/jayway/jsonpath/Predicate.java

@ -14,6 +14,7 @@
*/
package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.filter.EvaluatorFactory;
import com.jayway.jsonpath.spi.mapper.MappingException;
/**
@ -49,5 +50,11 @@ public interface Predicate {
* @return configuration
*/
Configuration configuration();
/**
* Factory to use for creating evaluators for filtering.
* @return Factory to use for creating evaluators for filtering.
*/
EvaluatorFactory evaluatorFactory();
}
}

268
json-path/src/main/java/com/jayway/jsonpath/internal/filter/DefaultEvaluatorFactory.java

@ -0,0 +1,268 @@
package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.JsonPathException;
import com.jayway.jsonpath.Predicate;
import java.util.EnumMap;
public class DefaultEvaluatorFactory implements EvaluatorFactory {
private static final EnumMap<RelationalOperator, Evaluator> evaluators
= new EnumMap<RelationalOperator, Evaluator>(RelationalOperator.class);
static {
evaluators.put(RelationalOperator.EXISTS, new ExistsEvaluator());
evaluators.put(RelationalOperator.NE, new NotEqualsEvaluator());
evaluators.put(RelationalOperator.TSNE, new TypeSafeNotEqualsEvaluator());
evaluators.put(RelationalOperator.EQ, new EqualsEvaluator());
evaluators.put(RelationalOperator.TSEQ, new TypeSafeEqualsEvaluator());
evaluators.put(RelationalOperator.LT, new LessThanEvaluator());
evaluators.put(RelationalOperator.LTE, new LessThanEqualsEvaluator());
evaluators.put(RelationalOperator.GT, new GreaterThanEvaluator());
evaluators.put(RelationalOperator.GTE, new GreaterThanEqualsEvaluator());
evaluators.put(RelationalOperator.REGEX, new RegexpEvaluator());
evaluators.put(RelationalOperator.SIZE, new SizeEvaluator());
evaluators.put(RelationalOperator.EMPTY, new EmptyEvaluator());
evaluators.put(RelationalOperator.IN, new InEvaluator());
evaluators.put(RelationalOperator.NIN, new NotInEvaluator());
evaluators.put(RelationalOperator.ALL, new AllEvaluator());
evaluators.put(RelationalOperator.CONTAINS, new ContainsEvaluator());
evaluators.put(RelationalOperator.MATCHES, new PredicateMatchEvaluator());
evaluators.put(RelationalOperator.TYPE, new TypeEvaluator());
}
@Override
public Evaluator createEvaluator(RelationalOperator operator) {
return evaluators.get(operator);
}
private static class ExistsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(!left.isBooleanNode() && !right.isBooleanNode()){
throw new JsonPathException("Failed to evaluate exists expression");
}
return left.asBooleanNode().getBoolean() == right.asBooleanNode().getBoolean();
}
}
private static class NotEqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
return !evaluators.get(RelationalOperator.EQ).evaluate(left, right, ctx);
}
}
private static class TypeSafeNotEqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
return !evaluators.get(RelationalOperator.TSEQ).evaluate(left, right, ctx);
}
}
private static class EqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(left.isJsonNode() && right.isJsonNode()){
return left.asJsonNode().equals(right.asJsonNode(), ctx);
} else {
return left.equals(right);
}
}
}
private static class TypeSafeEqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(!left.getClass().equals(right.getClass())){
return false;
}
return evaluators.get(RelationalOperator.EQ).evaluate(left, right, ctx);
}
}
private static class TypeEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
return right.asClassNode().getClazz() == left.type(ctx);
}
}
private static class LessThanEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(left.isNumberNode() && right.isNumberNode()){
return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) < 0;
} if(left.isStringNode() && right.isStringNode()){
return left.asStringNode().getString().compareTo(right.asStringNode().getString()) < 0;
}
return false;
}
}
private static class LessThanEqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(left.isNumberNode() && right.isNumberNode()){
return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) <= 0;
} if(left.isStringNode() && right.isStringNode()){
return left.asStringNode().getString().compareTo(right.asStringNode().getString()) <= 0;
}
return false;
}
}
private static class GreaterThanEvaluator implements Evaluator {
@Override
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()){
return left.asStringNode().getString().compareTo(right.asStringNode().getString()) > 0;
}
return false;
}
}
private static class GreaterThanEqualsEvaluator implements Evaluator {
@Override
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()){
return left.asStringNode().getString().compareTo(right.asStringNode().getString()) >= 0;
}
return false;
}
}
private static class SizeEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if (! right.isNumberNode()) {
return false;
}
int expectedSize = right.asNumberNode().getNumber().intValue();
if(left.isStringNode()){
return left.asStringNode().length() == expectedSize;
} else if(left.isJsonNode()){
return left.asJsonNode().length(ctx) == expectedSize;
}
return false;
}
}
private static class EmptyEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(left.isStringNode()){
return left.asStringNode().isEmpty() == right.asBooleanNode().getBoolean();
} else if(left.isJsonNode()){
return left.asJsonNode().isEmpty(ctx) == right.asBooleanNode().getBoolean();
}
return false;
}
}
private static class InEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
ValueNode.ValueListNode valueListNode;
if(right.isJsonNode()){
ValueNode vn = right.asJsonNode().asValueListNode(ctx);
if(vn.isUndefinedNode()){
return false;
} else {
valueListNode = vn.asValueListNode();
}
} else {
valueListNode = right.asValueListNode();
}
return valueListNode.contains(left);
}
}
private static class NotInEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
return !evaluators.get(RelationalOperator.IN).evaluate(left, right, ctx);
}
}
private static class AllEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
ValueNode.ValueListNode requiredValues = right.asValueListNode();
if(left.isJsonNode()){
ValueNode valueNode = left.asJsonNode().asValueListNode(ctx); //returns UndefinedNode if conversion is not possible
if(valueNode.isValueListNode()){
ValueNode.ValueListNode shouldContainAll = valueNode.asValueListNode();
for (ValueNode required : requiredValues) {
if(!shouldContainAll.contains(required)){
return false;
}
}
}
return true;
}
return false;
}
}
private static class ContainsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(left.isStringNode() && right.isStringNode()){
return left.asStringNode().contains(right.asStringNode().getString());
} else if(left.isJsonNode()){
ValueNode valueNode = left.asJsonNode().asValueListNode(ctx);
if(valueNode.isUndefinedNode()) return false;
else {
boolean res = valueNode.asValueListNode().contains(right);
return res;
}
}
return false;
}
}
private static class PredicateMatchEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
return right.asPredicateNode().getPredicate().apply(ctx);
}
}
private static class RegexpEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(!(left.isPatternNode() ^ right.isPatternNode())){
return false;
}
if (left.isPatternNode()) {
return matches(left.asPatternNode(), getInput(right));
} else {
return matches(right.asPatternNode(), getInput(left));
}
}
private boolean matches(ValueNode.PatternNode patternNode, String inputToMatch) {
return patternNode.getCompiledPattern().matcher(inputToMatch).matches();
}
private String getInput(ValueNode valueNode) {
String input = "";
if (valueNode.isStringNode() || valueNode.isNumberNode()) {
input = valueNode.asStringNode().getString();
} else if (valueNode.isBooleanNode()) {
input = valueNode.asBooleanNode().toString();
}
return input;
}
}
}

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

@ -1,267 +1,9 @@
// (c) Copyright 2016 Likelihood, Inc.
package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.JsonPathException;
import com.jayway.jsonpath.Predicate;
import java.util.HashMap;
import java.util.Map;
public class EvaluatorFactory {
private static final Map<RelationalOperator, Evaluator> evaluators = new HashMap<RelationalOperator, Evaluator>();
static {
evaluators.put(RelationalOperator.EXISTS, new ExistsEvaluator());
evaluators.put(RelationalOperator.NE, new NotEqualsEvaluator());
evaluators.put(RelationalOperator.TSNE, new TypeSafeNotEqualsEvaluator());
evaluators.put(RelationalOperator.EQ, new EqualsEvaluator());
evaluators.put(RelationalOperator.TSEQ, new TypeSafeEqualsEvaluator());
evaluators.put(RelationalOperator.LT, new LessThanEvaluator());
evaluators.put(RelationalOperator.LTE, new LessThanEqualsEvaluator());
evaluators.put(RelationalOperator.GT, new GreaterThanEvaluator());
evaluators.put(RelationalOperator.GTE, new GreaterThanEqualsEvaluator());
evaluators.put(RelationalOperator.REGEX, new RegexpEvaluator());
evaluators.put(RelationalOperator.SIZE, new SizeEvaluator());
evaluators.put(RelationalOperator.EMPTY, new EmptyEvaluator());
evaluators.put(RelationalOperator.IN, new InEvaluator());
evaluators.put(RelationalOperator.NIN, new NotInEvaluator());
evaluators.put(RelationalOperator.ALL, new AllEvaluator());
evaluators.put(RelationalOperator.CONTAINS, new ContainsEvaluator());
evaluators.put(RelationalOperator.MATCHES, new PredicateMatchEvaluator());
evaluators.put(RelationalOperator.TYPE, new TypeEvaluator());
}
public static Evaluator createEvaluator(RelationalOperator operator){
return evaluators.get(operator);
}
private static class ExistsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(!left.isBooleanNode() && !right.isBooleanNode()){
throw new JsonPathException("Failed to evaluate exists expression");
}
return left.asBooleanNode().getBoolean() == right.asBooleanNode().getBoolean();
}
}
private static class NotEqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
return !evaluators.get(RelationalOperator.EQ).evaluate(left, right, ctx);
}
}
private static class TypeSafeNotEqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
return !evaluators.get(RelationalOperator.TSEQ).evaluate(left, right, ctx);
}
}
private static class EqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(left.isJsonNode() && right.isJsonNode()){
return left.asJsonNode().equals(right.asJsonNode(), ctx);
} else {
return left.equals(right);
}
}
}
private static class TypeSafeEqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(!left.getClass().equals(right.getClass())){
return false;
}
return evaluators.get(RelationalOperator.EQ).evaluate(left, right, ctx);
}
}
private static class TypeEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
return right.asClassNode().getClazz() == left.type(ctx);
}
}
private static class LessThanEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(left.isNumberNode() && right.isNumberNode()){
return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) < 0;
} if(left.isStringNode() && right.isStringNode()){
return left.asStringNode().getString().compareTo(right.asStringNode().getString()) < 0;
}
return false;
}
}
private static class LessThanEqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(left.isNumberNode() && right.isNumberNode()){
return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) <= 0;
} if(left.isStringNode() && right.isStringNode()){
return left.asStringNode().getString().compareTo(right.asStringNode().getString()) <= 0;
}
return false;
}
}
private static class GreaterThanEvaluator implements Evaluator {
@Override
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()){
return left.asStringNode().getString().compareTo(right.asStringNode().getString()) > 0;
}
return false;
}
}
private static class GreaterThanEqualsEvaluator implements Evaluator {
@Override
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()){
return left.asStringNode().getString().compareTo(right.asStringNode().getString()) >= 0;
}
return false;
}
}
private static class SizeEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if (! right.isNumberNode()) {
return false;
}
int expectedSize = right.asNumberNode().getNumber().intValue();
if(left.isStringNode()){
return left.asStringNode().length() == expectedSize;
} else if(left.isJsonNode()){
return left.asJsonNode().length(ctx) == expectedSize;
}
return false;
}
}
private static class EmptyEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(left.isStringNode()){
return left.asStringNode().isEmpty() == right.asBooleanNode().getBoolean();
} else if(left.isJsonNode()){
return left.asJsonNode().isEmpty(ctx) == right.asBooleanNode().getBoolean();
}
return false;
}
}
private static class InEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
ValueNode.ValueListNode valueListNode;
if(right.isJsonNode()){
ValueNode vn = right.asJsonNode().asValueListNode(ctx);
if(vn.isUndefinedNode()){
return false;
} else {
valueListNode = vn.asValueListNode();
}
} else {
valueListNode = right.asValueListNode();
}
return valueListNode.contains(left);
}
}
private static class NotInEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
return !evaluators.get(RelationalOperator.IN).evaluate(left, right, ctx);
}
}
private static class AllEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
ValueNode.ValueListNode requiredValues = right.asValueListNode();
if(left.isJsonNode()){
ValueNode valueNode = left.asJsonNode().asValueListNode(ctx); //returns UndefinedNode if conversion is not possible
if(valueNode.isValueListNode()){
ValueNode.ValueListNode shouldContainAll = valueNode.asValueListNode();
for (ValueNode required : requiredValues) {
if(!shouldContainAll.contains(required)){
return false;
}
}
}
return true;
}
return false;
}
}
private static class ContainsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(left.isStringNode() && right.isStringNode()){
return left.asStringNode().contains(right.asStringNode().getString());
} else if(left.isJsonNode()){
ValueNode valueNode = left.asJsonNode().asValueListNode(ctx);
if(valueNode.isUndefinedNode()) return false;
else {
boolean res = valueNode.asValueListNode().contains(right);
return res;
}
}
return false;
}
}
private static class PredicateMatchEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
return right.asPredicateNode().getPredicate().apply(ctx);
}
}
private static class RegexpEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(!(left.isPatternNode() ^ right.isPatternNode())){
return false;
}
if (left.isPatternNode()) {
return matches(left.asPatternNode(), getInput(right));
} else {
return matches(right.asPatternNode(), getInput(left));
}
}
private boolean matches(ValueNode.PatternNode patternNode, String inputToMatch) {
return patternNode.getCompiledPattern().matcher(inputToMatch).matches();
}
private String getInput(ValueNode valueNode) {
String input = "";
if (valueNode.isStringNode() || valueNode.isNumberNode()) {
input = valueNode.asStringNode().getString();
} else if (valueNode.isBooleanNode()) {
input = valueNode.asBooleanNode().toString();
}
return input;
}
}
/**
* Interface for creating evaluators.
*/
public interface EvaluatorFactory {
Evaluator createEvaluator(RelationalOperator operator);
}

60
json-path/src/main/java/com/jayway/jsonpath/internal/filter/ImplicitNumericConversionEvaluatorFactory.java

@ -0,0 +1,60 @@
// (c) Copyright 2016 Likelihood, Inc.
package com.jayway.jsonpath.internal.filter;
import java.util.EnumMap;
import com.jayway.jsonpath.Predicate.PredicateContext;
import com.jayway.jsonpath.internal.filter.ValueNode.NumberNode;
/**
* Factory that supports implicit numeric conversions for evaluators.
*/
public class ImplicitNumericConversionEvaluatorFactory implements EvaluatorFactory {
private final EnumMap<RelationalOperator, Evaluator>
evaluators = new EnumMap<RelationalOperator, Evaluator>(RelationalOperator.class);
public ImplicitNumericConversionEvaluatorFactory(EvaluatorFactory delegateFactory) {
// for each operator, wrap just the ones that allow implicit numeric conversion.
for (RelationalOperator op : RelationalOperator.values()) {
Evaluator delegateEvaluator = delegateFactory.createEvaluator(op);
if (delegateEvaluator != null) {
evaluators.put(
op,
op.allowImplicitNumericConversion()
? new Wrapper(delegateEvaluator)
: delegateEvaluator);
}
}
}
@Override
public Evaluator createEvaluator(RelationalOperator operator) {
return evaluators.get(operator);
}
private static class Wrapper implements Evaluator {
Evaluator wrapped;
Wrapper(Evaluator wrapped) {
this.wrapped = wrapped;
}
@Override
public boolean evaluate(
ValueNode left, ValueNode right, PredicateContext ctx) {
final boolean eval = wrapped.evaluate(left, right, ctx);
if (!eval) {
if (left.isNumberNode() && right.isStringNode()) {
final ValueNode converted = right.asNumberNode();
return (converted != NumberNode.NAN) && wrapped.evaluate(left, converted, ctx);
}
if (left.isStringNode() && right.isNumberNode()) {
final ValueNode converted = left.asNumberNode();
return (converted != NumberNode.NAN) && wrapped.evaluate(converted, right, ctx);
}
}
return eval;
}
}
}

5
json-path/src/main/java/com/jayway/jsonpath/internal/filter/RelationalExpressionNode.java

@ -39,8 +39,9 @@ public class RelationalExpressionNode extends ExpressionNode {
if(right.isPathNode()){
r = right.asPathNode().evaluate(ctx);
}
Evaluator evaluator = EvaluatorFactory.createEvaluator(relationalOperator);
if(evaluator != null){
Evaluator evaluator = ctx.evaluatorFactory().createEvaluator(relationalOperator);
if(evaluator != null) {
return evaluator.evaluate(l, r, ctx);
}
return false;

27
json-path/src/main/java/com/jayway/jsonpath/internal/filter/RelationalOperator.java

@ -4,8 +4,9 @@ import com.jayway.jsonpath.InvalidPathException;
public enum RelationalOperator {
GTE(">="),
LTE("<="),
GTE(">=", true),
LTE("<=", true),
// EQ already support implicit numeric conversion in StringNode.equals and NumericNode.equals
EQ("=="),
/**
@ -18,8 +19,8 @@ public enum RelationalOperator {
* Type safe not equals
*/
TSNE("!=="),
LT("<"),
GT(">"),
LT("<", true),
GT(">", true),
REGEX("=~"),
NIN("NIN"),
IN("IN"),
@ -32,9 +33,14 @@ public enum RelationalOperator {
EMPTY("EMPTY");
private final String operatorString;
private final boolean allowImplicitNumericConversion;
RelationalOperator(String operatorString) {
this(operatorString, false);
}
RelationalOperator(String operatorString, boolean allowImplicitNumericConversion) {
this.operatorString = operatorString;
this.allowImplicitNumericConversion = allowImplicitNumericConversion;
}
public static RelationalOperator fromString(String operatorString){
@ -46,8 +52,21 @@ public enum RelationalOperator {
throw new InvalidPathException("Filter operator " + operatorString + " is not supported!");
}
public boolean allowImplicitNumericConversion() {
return allowImplicitNumericConversion;
}
@Override
public String toString() {
return operatorString;
}
public static final EvaluatorFactory DEFAULT_EVALUATOR_FACTORY = new DefaultEvaluatorFactory();
public static final EvaluatorFactory IMPLICIT_NUMERIC_CONVERSION_EVALUATOR_FACTORY
= new ImplicitNumericConversionEvaluatorFactory(DEFAULT_EVALUATOR_FACTORY);
public static EvaluatorFactory getEvaluatorFactory(boolean allowImplicitNumericConversion) {
return allowImplicitNumericConversion
? IMPLICIT_NUMERIC_CONVERSION_EVALUATOR_FACTORY : DEFAULT_EVALUATOR_FACTORY;
}
}

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

@ -15,8 +15,11 @@
package com.jayway.jsonpath.internal.path;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.Predicate;
import com.jayway.jsonpath.internal.Path;
import com.jayway.jsonpath.internal.filter.EvaluatorFactory;
import com.jayway.jsonpath.internal.filter.RelationalOperator;
import com.jayway.jsonpath.spi.mapper.MappingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -31,12 +34,15 @@ public class PredicateContextImpl implements Predicate.PredicateContext {
private final Object rootDocument;
private final Configuration configuration;
private final HashMap<Path, Object> documentPathCache;
private final EvaluatorFactory evaluatorFactory;
public PredicateContextImpl(Object contextDocument, Object rootDocument, Configuration configuration, HashMap<Path, Object> documentPathCache) {
this.contextDocument = contextDocument;
this.rootDocument = rootDocument;
this.configuration = configuration;
this.documentPathCache = documentPathCache;
this.evaluatorFactory = RelationalOperator.getEvaluatorFactory(
configuration.containsOption(Option.IMPLICIT_NUMERIC_CONVERSIONS));
}
public Object evaluate(Path path){
@ -79,4 +85,8 @@ public class PredicateContextImpl implements Predicate.PredicateContext {
return configuration;
}
@Override
public EvaluatorFactory evaluatorFactory() {
return evaluatorFactory;
}
}

5
json-path/src/test/java/com/jayway/jsonpath/BaseTest.java

@ -119,7 +119,10 @@ public class BaseTest {
"}";
public Predicate.PredicateContext createPredicateContext(final Object check) {
return createPredicateContext(check, Configuration.defaultConfiguration());
}
return new PredicateContextImpl(check, check, Configuration.defaultConfiguration(), new HashMap<Path, Object>());
public Predicate.PredicateContext createPredicateContext(final Object check, Configuration configuration) {
return new PredicateContextImpl(check, check, configuration, new HashMap<Path, Object>());
}
}

349
json-path/src/test/java/com/jayway/jsonpath/FilterTest.java

@ -1,10 +1,10 @@
package com.jayway.jsonpath;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.regex.Pattern;
import static com.jayway.jsonpath.Criteria.where;
@ -12,10 +12,27 @@ import static com.jayway.jsonpath.Filter.filter;
import static com.jayway.jsonpath.Filter.parse;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(Parameterized.class)
public class FilterTest extends BaseTest {
private final Configuration configuration;
private Object json;
Object json = Configuration.defaultConfiguration().jsonProvider().parse(
public FilterTest(Configuration configuration) {
this.configuration = configuration;
json = configuration.jsonProvider().parse(jsonString);
}
// Run test with configurations with implicit numeric conversions turned off and on.
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
{ Configuration.defaultConfiguration() },
{ Configuration.defaultConfiguration().addOptions(Option.IMPLICIT_NUMERIC_CONVERSIONS) },
});
}
private String jsonString =
"{" +
" \"int-key\" : 1, " +
" \"long-key\" : 3000000000, " +
@ -24,12 +41,12 @@ public class FilterTest extends BaseTest {
" \"null-key\" : null, " +
" \"string-key\" : \"string\", " +
" \"string-key-empty\" : \"\", " +
" \"string-numeric-key\": \"10\", " +
" \"char-key\" : \"c\", " +
" \"arr-empty\" : [], " +
" \"int-arr\" : [0,1,2,3,4], " +
" \"string-arr\" : [\"a\",\"b\",\"c\",\"d\",\"e\"] " +
"}"
);
"}";
//----------------------------------------------------------------------------
//
@ -38,55 +55,62 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void int_eq_evals() {
assertThat(filter(where("int-key").eq(1)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("int-key").eq(666)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("int-key").eq(1)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("int-key").eq(666)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void int_eq_string_evals() {
assertThat(filter(where("int-key").eq("1")).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("int-key").eq("666")).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("int-key").eq("1")).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("int-key").eq("666")).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(Filter.parse("[?(1 == '1')]").apply(createPredicateContext(json))).isEqualTo(true);
assertThat(Filter.parse("[?('1' == 1)]").apply(createPredicateContext(json))).isEqualTo(true);
assertThat(Filter.parse("[?(1 == '1')]").apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(Filter.parse("[?('1' == 1)]").apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(Filter.parse("[?(1 === '1')]").apply(createPredicateContext(json))).isEqualTo(false);
assertThat(Filter.parse("[?('1' === 1)]").apply(createPredicateContext(json))).isEqualTo(false);
assertThat(Filter.parse("[?(1 === '1')]").apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(Filter.parse("[?('1' === 1)]").apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(Filter.parse("[?(1 === 1)]").apply(createPredicateContext(json))).isEqualTo(true);
assertThat(Filter.parse("[?(1 === 1)]").apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void long_eq_evals() {
assertThat(filter(where("long-key").eq(3000000000L)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("long-key").eq(666L)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("long-key").eq(3000000000L)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("long-key").eq(666L)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void double_eq_evals() {
assertThat(filter(where("double-key").eq(10.1D)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("double-key").eq(10.10D)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("double-key").eq(10.11D)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("double-key").eq(10.1D)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("double-key").eq(10.10D)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("double-key").eq(10.11D)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void string_eq_evals() {
assertThat(filter(where("string-key").eq("string")).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-key").eq("666")).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-key").eq("string")).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("string-key").eq("666")).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void boolean_eq_evals() {
assertThat(filter(where("boolean-key").eq(true)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("boolean-key").eq(false)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("boolean-key").eq(true)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("boolean-key").eq(false)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void null_eq_evals() {
assertThat(filter(where("null-key").eq(null)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("null-key").eq("666")).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-key").eq(null)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("null-key").eq(null)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("null-key").eq("666")).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("string-key").eq(null)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void implicit_numeric_conversion_eq_evals() {
// equals supports implicit numeric conversion in all cases.
assertThat(filter(where("string-numeric-key").eq(10L)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("double-key").eq("10.1")).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
@ -103,40 +127,47 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void int_ne_evals() {
assertThat(filter(where("int-key").ne(1)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("int-key").ne(666)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("int-key").ne(1)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("int-key").ne(666)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void long_ne_evals() {
assertThat(filter(where("long-key").ne(3000000000L)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("long-key").ne(666L)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("long-key").ne(3000000000L)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("long-key").ne(666L)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void double_ne_evals() {
assertThat(filter(where("double-key").ne(10.1D)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("double-key").ne(10.10D)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("double-key").ne(10.11D)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("double-key").ne(10.1D)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("double-key").ne(10.10D)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("double-key").ne(10.11D)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void string_ne_evals() {
assertThat(filter(where("string-key").ne("string")).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-key").ne("666")).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-key").ne("string")).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("string-key").ne("666")).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void boolean_ne_evals() {
assertThat(filter(where("boolean-key").ne(true)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("boolean-key").ne(false)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("boolean-key").ne(true)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("boolean-key").ne(false)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void null_ne_evals() {
assertThat(filter(where("null-key").ne(null)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("null-key").ne("666")).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-key").ne(null)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("null-key").ne(null)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("null-key").ne("666")).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("string-key").ne(null)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void implicit_numeric_conversion_ne_evals() {
// equals supports implicit numeric conversion in all cases, so ne does as well.
assertThat(filter(where("string-numeric-key").ne(10L)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("double-key").ne("10.1")).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
//----------------------------------------------------------------------------
@ -146,26 +177,38 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void int_lt_evals() {
assertThat(filter(where("int-key").lt(10)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("int-key").lt(0)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("int-key").lt(10)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("int-key").lt(0)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void long_lt_evals() {
assertThat(filter(where("long-key").lt(4000000000L)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("long-key").lt(666L)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("long-key").lt(4000000000L)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("long-key").lt(666L)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void double_lt_evals() {
assertThat(filter(where("double-key").lt(100.1D)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("double-key").lt(1.1D)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("double-key").lt(100.1D)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("double-key").lt(1.1D)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void string_lt_evals() {
assertThat(filter(where("char-key").lt("x")).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("char-key").lt("a")).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("char-key").lt("x")).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("char-key").lt("a")).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void implicit_numeric_conversion_lt_evals() {
assertThat(filter(where("string-numeric-key").lt(100L)).apply(createPredicateContext(json, configuration)))
.isEqualTo(configuration.containsOption(Option.IMPLICIT_NUMERIC_CONVERSIONS));
assertThat(filter(where("string-numeric-key").lt(1L)).apply(createPredicateContext(json, configuration)))
.isEqualTo(false);
assertThat(filter(where("double-key").lt("100.1")).apply(createPredicateContext(json, configuration)))
.isEqualTo(configuration.containsOption(Option.IMPLICIT_NUMERIC_CONVERSIONS));
assertThat(filter(where("double-key").lt("1.1")).apply(createPredicateContext(json, configuration)))
.isEqualTo(false);
}
//----------------------------------------------------------------------------
@ -175,23 +218,39 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void int_lte_evals() {
assertThat(filter(where("int-key").lte(10)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("int-key").lte(1)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("int-key").lte(0)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("int-key").lte(10)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("int-key").lte(1)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("int-key").lte(0)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void long_lte_evals() {
assertThat(filter(where("long-key").lte(4000000000L)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("long-key").lte(3000000000L)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("long-key").lte(666L)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("long-key").lte(4000000000L)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("long-key").lte(3000000000L)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("long-key").lte(666L)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void double_lte_evals() {
assertThat(filter(where("double-key").lte(100.1D)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("double-key").lte(10.1D)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("double-key").lte(1.1D)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("double-key").lte(100.1D)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("double-key").lte(10.1D)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("double-key").lte(1.1D)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void implicit_numeric_conversion_lte_evals() {
assertThat(filter(where("string-numeric-key").lte(100L)).apply(createPredicateContext(json, configuration)))
.isEqualTo(configuration.containsOption(Option.IMPLICIT_NUMERIC_CONVERSIONS));
assertThat(filter(where("string-numeric-key").lte(10L)).apply(createPredicateContext(json, configuration)))
.isEqualTo(configuration.containsOption(Option.IMPLICIT_NUMERIC_CONVERSIONS));
assertThat(filter(where("string-numeric-key").lte(1L)).apply(createPredicateContext(json, configuration)))
.isEqualTo(false);
assertThat(filter(where("double-key").lte("100.1")).apply(createPredicateContext(json, configuration)))
.isEqualTo(configuration.containsOption(Option.IMPLICIT_NUMERIC_CONVERSIONS));
assertThat(filter(where("double-key").lte("10.1")).apply(createPredicateContext(json, configuration)))
.isEqualTo(configuration.containsOption(Option.IMPLICIT_NUMERIC_CONVERSIONS));
assertThat(filter(where("double-key").lte("1.1")).apply(createPredicateContext(json, configuration)))
.isEqualTo(false);
}
//----------------------------------------------------------------------------
@ -201,26 +260,38 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void int_gt_evals() {
assertThat(filter(where("int-key").gt(10)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("int-key").gt(0)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("int-key").gt(10)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("int-key").gt(0)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void long_gt_evals() {
assertThat(filter(where("long-key").gt(4000000000L)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("long-key").gt(666L)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("long-key").gt(4000000000L)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("long-key").gt(666L)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void double_gt_evals() {
assertThat(filter(where("double-key").gt(100.1D)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("double-key").gt(1.1D)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("double-key").gt(100.1D)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("double-key").gt(1.1D)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void string_gt_evals() {
assertThat(filter(where("char-key").gt("x")).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("char-key").gt("a")).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("char-key").gt("x")).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("char-key").gt("a")).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void implicit_numeric_conversion_gt_evals() {
assertThat(filter(where("string-numeric-key").gt(100L)).apply(createPredicateContext(json, configuration)))
.isEqualTo(false);
assertThat(filter(where("string-numeric-key").gt(1L)).apply(createPredicateContext(json, configuration)))
.isEqualTo(configuration.containsOption(Option.IMPLICIT_NUMERIC_CONVERSIONS));
assertThat(filter(where("double-key").gt("100.1")).apply(createPredicateContext(json, configuration)))
.isEqualTo(false);
assertThat(filter(where("double-key").gt("1.1")).apply(createPredicateContext(json, configuration)))
.isEqualTo(configuration.containsOption(Option.IMPLICIT_NUMERIC_CONVERSIONS));
}
//----------------------------------------------------------------------------
@ -230,23 +301,39 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void int_gte_evals() {
assertThat(filter(where("int-key").gte(10)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("int-key").gte(1)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("int-key").gte(0)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("int-key").gte(10)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("int-key").gte(1)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("int-key").gte(0)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void long_gte_evals() {
assertThat(filter(where("long-key").gte(4000000000L)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("long-key").gte(3000000000L)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("long-key").gte(666L)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("long-key").gte(4000000000L)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("long-key").gte(3000000000L)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("long-key").gte(666L)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void double_gte_evals() {
assertThat(filter(where("double-key").gte(100.1D)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("double-key").gte(10.1D)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("double-key").gte(1.1D)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("double-key").gte(100.1D)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("double-key").gte(10.1D)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("double-key").gte(1.1D)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@Test
public void implicit_numeric_conversion_gte_evals() {
assertThat(filter(where("string-numeric-key").gte(100L)).apply(createPredicateContext(json, configuration)))
.isEqualTo(false);
assertThat(filter(where("string-numeric-key").gte(10L)).apply(createPredicateContext(json, configuration)))
.isEqualTo(configuration.containsOption(Option.IMPLICIT_NUMERIC_CONVERSIONS));
assertThat(filter(where("string-numeric-key").gte(1L)).apply(createPredicateContext(json, configuration)))
.isEqualTo(configuration.containsOption(Option.IMPLICIT_NUMERIC_CONVERSIONS));
assertThat(filter(where("double-key").gte("100.1")).apply(createPredicateContext(json, configuration)))
.isEqualTo(false);
assertThat(filter(where("double-key").gte("10.1")).apply(createPredicateContext(json, configuration)))
.isEqualTo(configuration.containsOption(Option.IMPLICIT_NUMERIC_CONVERSIONS));
assertThat(filter(where("double-key").gte("1.1")).apply(createPredicateContext(json, configuration)))
.isEqualTo(configuration.containsOption(Option.IMPLICIT_NUMERIC_CONVERSIONS));
}
//----------------------------------------------------------------------------
@ -256,10 +343,10 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void string_regex_evals() {
assertThat(filter(where("string-key").regex(Pattern.compile("^string$"))).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-key").regex(Pattern.compile("^tring$"))).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("null-key").regex(Pattern.compile("^string$"))).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("int-key").regex(Pattern.compile("^string$"))).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-key").regex(Pattern.compile("^string$"))).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("string-key").regex(Pattern.compile("^tring$"))).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("null-key").regex(Pattern.compile("^string$"))).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("int-key").regex(Pattern.compile("^string$"))).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
//----------------------------------------------------------------------------
@ -272,7 +359,7 @@ public class FilterTest extends BaseTest {
String nest = "{\"a\":true}";
String arr = "[1,2]";
String json = "{\"foo\":" + arr + ", \"bar\":" + nest + "}";
Object tree = Configuration.defaultConfiguration().jsonProvider().parse(json);
Object tree = configuration.jsonProvider().parse(json);
Predicate.PredicateContext context = createPredicateContext(tree);
Filter farr = parse("[?(@.foo == " + arr + ")]");
//Filter fobjF = parse("[?(@.foo == " + nest + ")]");
@ -289,11 +376,11 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void string_in_evals() {
assertThat(filter(where("string-key").in("a", null, "string")).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-key").in("a", null)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("null-key").in("a", null)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("null-key").in("a", "b")).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-arr").in("a")).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-key").in("a", null, "string")).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("string-key").in("a", null)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("null-key").in("a", null)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("null-key").in("a", "b")).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("string-arr").in("a")).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
//----------------------------------------------------------------------------
@ -303,11 +390,11 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void string_nin_evals() {
assertThat(filter(where("string-key").nin("a", null, "string")).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-key").nin("a", null)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("null-key").nin("a", null)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("null-key").nin("a", "b")).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-arr").nin("a")).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-key").nin("a", null, "string")).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("string-key").nin("a", null)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("null-key").nin("a", null)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("null-key").nin("a", "b")).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("string-arr").nin("a")).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
@ -318,17 +405,17 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void int_all_evals() {
assertThat(filter(where("int-arr").all(0,1)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("int-arr").all(0,7)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("int-arr").all(0,1)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("int-arr").all(0,7)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void string_all_evals() {
assertThat(filter(where("string-arr").all("a","b")).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-arr").all("a","x")).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-arr").all("a","b")).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("string-arr").all("a","x")).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void not_array_all_evals() {
assertThat(filter(where("string-key").all("a","b")).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-key").all("a","b")).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
//----------------------------------------------------------------------------
@ -338,24 +425,24 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void array_size_evals() {
assertThat(filter(where("string-arr").size(5)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-arr").size(7)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-arr").size(5)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("string-arr").size(7)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void string_size_evals() {
assertThat(filter(where("string-key").size(6)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-key").size(7)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-key").size(6)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("string-key").size(7)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void other_size_evals() {
assertThat(filter(where("int-key").size(6)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("int-key").size(6)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@Test
public void null_size_evals() {
assertThat(filter(where("null-key").size(6)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("null-key").size(6)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
//----------------------------------------------------------------------------
@ -365,11 +452,11 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void exists_evals() {
assertThat(filter(where("string-key").exists(true)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-key").exists(false)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-key").exists(true)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("string-key").exists(false)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("missing-key").exists(true)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("missing-key").exists(false)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("missing-key").exists(true)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("missing-key").exists(false)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
//----------------------------------------------------------------------------
@ -379,15 +466,15 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void type_evals() {
assertThat(filter(where("string-key").type(String.class)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-key").type(Number.class)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-key").type(String.class)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("string-key").type(Number.class)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("int-key").type(String.class)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("int-key").type(Number.class)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("int-key").type(String.class)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("int-key").type(Number.class)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("null-key").type(String.class)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("null-key").type(String.class)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("int-arr").type(List.class)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("int-arr").type(List.class)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
//----------------------------------------------------------------------------
@ -397,13 +484,13 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void not_empty_evals() {
assertThat(filter(where("string-key").notEmpty()).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-key-empty").notEmpty()).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-key").notEmpty()).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("string-key-empty").notEmpty()).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("int-arr").notEmpty()).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("arr-empty").notEmpty()).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("int-arr").notEmpty()).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("arr-empty").notEmpty()).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("null-key").notEmpty()).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("null-key").notEmpty()).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
//----------------------------------------------------------------------------
@ -413,20 +500,20 @@ public class FilterTest extends BaseTest {
//----------------------------------------------------------------------------
@Test
public void empty_evals() {
assertThat(filter(where("string-key").empty(false)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-key").empty(true)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-key").empty(false)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("string-key").empty(true)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("string-key-empty").empty(true)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-key-empty").empty(false)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("string-key-empty").empty(true)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("string-key-empty").empty(false)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("int-arr").empty(false)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("int-arr").empty(true)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("int-arr").empty(false)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("int-arr").empty(true)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("arr-empty").empty(true)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("arr-empty").empty(false)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("arr-empty").empty(true)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
assertThat(filter(where("arr-empty").empty(false)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("null-key").empty(true)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("null-key").empty(false)).apply(createPredicateContext(json))).isEqualTo(false);
assertThat(filter(where("null-key").empty(true)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
assertThat(filter(where("null-key").empty(false)).apply(createPredicateContext(json, configuration))).isEqualTo(false);
}
@ -450,7 +537,7 @@ public class FilterTest extends BaseTest {
return i == 1;
}
};
assertThat(filter(where("string-key").eq("string").and("$").matches(p)).apply(createPredicateContext(json))).isEqualTo(true);
assertThat(filter(where("string-key").eq("string").and("$").matches(p)).apply(createPredicateContext(json, configuration))).isEqualTo(true);
}
//----------------------------------------------------------------------------
@ -482,14 +569,14 @@ public class FilterTest extends BaseTest {
@Test
public void testFilterWithOrShortCircuit1() throws Exception {
Object json = Configuration.defaultConfiguration().jsonProvider().parse( "{\"firstname\":\"Bob\",\"surname\":\"Smith\",\"age\":30}");
assertThat(Filter.parse("[?((@.firstname == 'Bob' || @.firstname == 'Jane') && @.surname == 'Doe')]").apply(createPredicateContext(json))).isFalse();
Object json = configuration.jsonProvider().parse( "{\"firstname\":\"Bob\",\"surname\":\"Smith\",\"age\":30}");
assertThat(Filter.parse("[?((@.firstname == 'Bob' || @.firstname == 'Jane') && @.surname == 'Doe')]").apply(createPredicateContext(json, configuration))).isFalse();
}
@Test
public void testFilterWithOrShortCircuit2() throws Exception {
Object json = Configuration.defaultConfiguration().jsonProvider().parse("{\"firstname\":\"Bob\",\"surname\":\"Smith\",\"age\":30}");
assertThat(Filter.parse("[?((@.firstname == 'Bob' || @.firstname == 'Jane') && @.surname == 'Smith')]").apply(createPredicateContext(json))).isTrue();
Object json = configuration.jsonProvider().parse("{\"firstname\":\"Bob\",\"surname\":\"Smith\",\"age\":30}");
assertThat(Filter.parse("[?((@.firstname == 'Bob' || @.firstname == 'Jane') && @.surname == 'Smith')]").apply(createPredicateContext(json, configuration))).isTrue();
}
@Test

2
json-path/src/test/java/com/jayway/jsonpath/internal/filter/RegexpEvaluatorTest.java

@ -34,7 +34,7 @@ public class RegexpEvaluatorTest extends BaseTest {
@Test
public void should_evaluate_regular_expression() {
//given
Evaluator evaluator = EvaluatorFactory.createEvaluator(RelationalOperator.REGEX);
Evaluator evaluator = new DefaultEvaluatorFactory().createEvaluator(RelationalOperator.REGEX);
ValueNode patternNode = createPatternNode(regexp);
Predicate.PredicateContext ctx = createPredicateContext();

7
json-path/src/test/java/com/jayway/jsonpath/old/IssuesTest.java

@ -11,6 +11,8 @@ import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.Utils;
import com.jayway.jsonpath.internal.filter.DefaultEvaluatorFactory;
import com.jayway.jsonpath.internal.filter.EvaluatorFactory;
import com.jayway.jsonpath.spi.cache.LRUCache;
import com.jayway.jsonpath.spi.json.GsonJsonProvider;
import com.jayway.jsonpath.spi.json.JsonProvider;
@ -837,6 +839,11 @@ public class IssuesTest extends BaseTest {
public Configuration configuration() {
return Configuration.defaultConfiguration();
}
@Override
public EvaluatorFactory evaluatorFactory() {
return new DefaultEvaluatorFactory();
}
};
}

Loading…
Cancel
Save