From ca4d18911ec8fdb6d9dcd37366e6326853f62440 Mon Sep 17 00:00:00 2001 From: Kalle Stenflo Date: Sun, 26 Oct 2014 16:20:31 +0100 Subject: [PATCH] Inline criteria handles path stmt on both sides of operator. --- .../src/main/resources/webapp/index.html | 2 +- .../java/com/jayway/jsonpath/Criteria.java | 371 ++++++++++-------- .../com/jayway/jsonpath/InlineFilterTest.java | 34 ++ .../com/jayway/jsonpath/old/FilterTest.java | 6 +- 4 files changed, 241 insertions(+), 172 deletions(-) diff --git a/json-path-web-test/src/main/resources/webapp/index.html b/json-path-web-test/src/main/resources/webapp/index.html index e1ef5ca3..d6f0cb6e 100644 --- a/json-path-web-test/src/main/resources/webapp/index.html +++ b/json-path-web-test/src/main/resources/webapp/index.html @@ -147,7 +147,7 @@

- About implementation... + About implementation...  millis
diff --git a/json-path/src/main/java/com/jayway/jsonpath/Criteria.java b/json-path/src/main/java/com/jayway/jsonpath/Criteria.java index 2d537d6b..0c992d5b 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/Criteria.java +++ b/json-path/src/main/java/com/jayway/jsonpath/Criteria.java @@ -48,18 +48,18 @@ public class Criteria implements Predicate { CriteriaType.GT.toString() }; - private final Path path; + private Object left; private CriteriaType criteriaType; - private Object expected; + private Object right; private final List criteriaChain; private static enum CriteriaType { EQ { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { - boolean res = (0 == safeCompare(expected, actual)); - if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res); + boolean eval(Object left, Object right, PredicateContext ctx) { + boolean res = (0 == safeCompare(left, right)); + if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", right, name(), left, res); return res; } @@ -70,9 +70,9 @@ public class Criteria implements Predicate { }, NE { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { - boolean res = (0 != safeCompare(expected, actual)); - if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res); + boolean eval(Object left, Object right, PredicateContext ctx) { + boolean res = (0 != safeCompare(left, right)); + if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", right, name(), left, res); return res; } @@ -83,12 +83,12 @@ public class Criteria implements Predicate { }, GT { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { - if ((expected == null) ^ (actual == null)) { + boolean eval(Object left, Object right, PredicateContext ctx) { + if ((left == null) ^ (right == null)) { return false; } - boolean res = (0 > safeCompare(expected, actual)); - if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res); + boolean res = (0 > safeCompare(left, right)); + if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", right, name(), left, res); return res; } @Override @@ -98,12 +98,12 @@ public class Criteria implements Predicate { }, GTE { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { - if ((expected == null) ^ (actual == null)) { + boolean eval(Object left, Object right, PredicateContext ctx) { + if ((left == null) ^ (right == null)) { return false; } - boolean res = (0 >= safeCompare(expected, actual)); - if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res); + boolean res = (0 >= safeCompare(left, right)); + if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", right, name(), left, res); return res; } @Override @@ -113,12 +113,12 @@ public class Criteria implements Predicate { }, LT { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { - if ((expected == null) ^ (actual == null)) { + boolean eval(Object left, Object right, PredicateContext ctx) { + if ((left == null) ^ (right == null)) { return false; } - boolean res = (0 < safeCompare(expected, actual)); - if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res); + boolean res = (0 < safeCompare(left, right)); + if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", right, name(), left, res); return res; } @Override @@ -128,12 +128,12 @@ public class Criteria implements Predicate { }, LTE { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { - if ((expected == null) ^ (actual == null)) { + boolean eval(Object left, Object right, PredicateContext ctx) { + if ((left == null) ^ (right == null)) { return false; } - boolean res = (0 <= safeCompare(expected, actual)); - if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res); + boolean res = (0 <= safeCompare(left, right)); + if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", right, name(), left, res); return res; } @Override @@ -143,37 +143,37 @@ public class Criteria implements Predicate { }, IN { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { + boolean eval(Object left, Object right, PredicateContext ctx) { boolean res = false; - Collection exps = (Collection) expected; + Collection exps = (Collection) left; for (Object exp : exps) { - if (0 == safeCompare(exp, actual)) { + if (0 == safeCompare(exp, right)) { res = true; break; } } - if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", actual, name(), join(", ", exps), res); + if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", right, name(), join(", ", exps), res); return res; } }, NIN { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { - Collection nexps = (Collection) expected; - boolean res = !nexps.contains(actual); - if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", actual, name(), join(", ", nexps), res); + boolean eval(Object left, Object right, PredicateContext ctx) { + Collection nexps = (Collection) left; + boolean res = !nexps.contains(right); + if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", right, name(), join(", ", nexps), res); return res; } }, ALL { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { + boolean eval(Object left, Object right, PredicateContext ctx) { boolean res = true; - Collection exps = (Collection) expected; - if (ctx.configuration().jsonProvider().isArray(actual)) { + Collection exps = (Collection) left; + if (ctx.configuration().jsonProvider().isArray(right)) { for (Object exp : exps) { boolean found = false; - for (Object check : ctx.configuration().jsonProvider().toIterable(actual)) { + for (Object check : ctx.configuration().jsonProvider().toIterable(right)) { if (0 == safeCompare(exp, check)) { found = true; break; @@ -184,7 +184,7 @@ public class Criteria implements Predicate { break; } } - if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", join(", ", ctx.configuration().jsonProvider().toIterable(actual)), name(), join(", ", exps), res); + if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", join(", ", ctx.configuration().jsonProvider().toIterable(right)), name(), join(", ", exps), res); } else { res = false; if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", "", name(), join(", ", exps), res); @@ -194,71 +194,71 @@ public class Criteria implements Predicate { }, SIZE { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { - int size = (Integer) expected; + boolean eval(Object left, Object right, PredicateContext ctx) { + int size = (Integer) left; boolean res; - if (ctx.configuration().jsonProvider().isArray(actual)) { - int length = ctx.configuration().jsonProvider().length(actual); + if (ctx.configuration().jsonProvider().isArray(right)) { + int length = ctx.configuration().jsonProvider().length(right); res = (length == size); if(logger.isDebugEnabled()) logger.debug("Array with size {} {} {} => {}", length, name(), size, res); - } else if (actual instanceof String) { - int length = ((String) actual).length(); + } else if (right instanceof String) { + int length = ((String) right).length(); res = length == size; if(logger.isDebugEnabled()) logger.debug("String with length {} {} {} => {}", length, name(), size, res); } else { res = false; - if(logger.isDebugEnabled()) logger.debug("{} {} {} => {}", actual == null ? "null" : actual.getClass().getName(), name(), size, res); + if(logger.isDebugEnabled()) logger.debug("{} {} {} => {}", right == null ? "null" : right.getClass().getName(), name(), size, res); } return res; } }, EXISTS { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { + boolean eval(Object left, Object right, PredicateContext ctx) { //This must be handled outside throw new UnsupportedOperationException(); } }, TYPE { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { - final Class expType = (Class) expected; - final Class actType = actual == null ? null : actual.getClass(); + boolean eval(Object left, Object right, PredicateContext ctx) { + final Class expType = (Class) left; + final Class actType = right == null ? null : right.getClass(); return actType != null && expType.isAssignableFrom(actType); } }, REGEX { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { + boolean eval(Object left, Object right, PredicateContext ctx) { boolean res = false; - final Pattern pattern = (Pattern) expected; - if (actual != null && actual instanceof String) { - res = pattern.matcher(actual.toString()).matches(); + final Pattern pattern = (Pattern) left; + if (right != null && right instanceof String) { + res = pattern.matcher(right.toString()).matches(); } - if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", actual, name(), expected.toString(), res); + if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", right, name(), left.toString(), res); return res; } }, MATCHES { @Override - boolean eval(Object expected, final Object actual, final PredicateContext ctx) { + boolean eval(Object left, final Object right, final PredicateContext ctx) { PredicateContextImpl pci = (PredicateContextImpl) ctx; - Predicate exp = (Predicate) expected; - return exp.apply(new PredicateContextImpl(actual, ctx.root(), ctx.configuration(), pci.documentPathCache())); + Predicate exp = (Predicate) left; + return exp.apply(new PredicateContextImpl(right, ctx.root(), ctx.configuration(), pci.documentPathCache())); } }, NOT_EMPTY { @Override - boolean eval(Object expected, Object actual, PredicateContext ctx) { + boolean eval(Object left, Object right, PredicateContext ctx) { boolean res = false; - if (actual != null) { - if (ctx.configuration().jsonProvider().isArray(actual)) { - int len = ctx.configuration().jsonProvider().length(actual); + if (right != null) { + if (ctx.configuration().jsonProvider().isArray(right)) { + int len = ctx.configuration().jsonProvider().length(right); res = (0 != len); if(logger.isDebugEnabled()) logger.debug("array length = {} {} => {}", len, name(), res); - } else if (actual instanceof String) { - int len = ((String) actual).length(); + } else if (right instanceof String) { + int len = ((String) right).length(); res = (0 != len); if(logger.isDebugEnabled()) logger.debug("string length = {} {} => {}", len, name(), res); } @@ -267,7 +267,7 @@ public class Criteria implements Predicate { } }; - abstract boolean eval(Object expected, Object actual, PredicateContext ctx); + abstract boolean eval(Object left, Object right, PredicateContext ctx); public static CriteriaType parse(String str) { if ("==".equals(str)) { @@ -288,23 +288,26 @@ public class Criteria implements Predicate { } } - private Criteria(List criteriaChain, Path path) { - if (!path.isDefinite()) { - throw new InvalidCriteriaException("A criteria path must be definite. The path " + path.toString() + " is not!"); + private Criteria(List criteriaChain, Object left) { + + if(left instanceof Path) { + if (!((Path)left).isDefinite()) { + throw new InvalidCriteriaException("A criteria path must be definite. The path " + left.toString() + " is not!"); + } } - this.path = path; + this.left = left; this.criteriaChain = criteriaChain; this.criteriaChain.add(this); } - private Criteria(Path path) { - this(new LinkedList(), path); + private Criteria(Object left) { + this(new LinkedList(), left); } - private Criteria(Path path, CriteriaType criteriaType, Object expected) { - this(new LinkedList(), path); + private Criteria(Object left, CriteriaType criteriaType, Object right) { + this(new LinkedList(), left); this.criteriaType = criteriaType; - this.expected = expected; + this.right = right; } @@ -318,35 +321,39 @@ public class Criteria implements Predicate { return true; } + private Object evaluateIfPath(Object target, PredicateContext ctx){ + Object res = target; + if(res instanceof Path){ + Path leftPath = (Path) target; + + if(ctx instanceof PredicateContextImpl){ + //This will use cache for document ($) queries + PredicateContextImpl ctxi = (PredicateContextImpl) ctx; + res = ctxi.evaluate(leftPath); + } else { + Object doc = leftPath.isRootPath()?ctx.root():ctx.item(); + res = leftPath.evaluate(doc, ctx.root(), ctx.configuration()).getValue(); + } + } + return res; + } + private boolean eval(PredicateContext ctx) { if (CriteriaType.EXISTS == criteriaType) { - boolean exists = ((Boolean) expected); + boolean exists = ((Boolean) right); try { Configuration c = Configuration.builder().jsonProvider(ctx.configuration().jsonProvider()).options(Option.REQUIRE_PROPERTIES).build(); - path.evaluate(ctx.item(), ctx.root(), c).getValue(); + ((Path)left).evaluate(ctx.item(), ctx.root(), c).getValue(); return exists; } catch (PathNotFoundException e) { return !exists; } } else { try { - final Object actual = path.evaluate(ctx.item(), ctx.root(), ctx.configuration()).getValue(); - - Object expectedVal = expected; - if(expected instanceof Path){ - Path expectedPath = (Path) expected; - - if(ctx instanceof PredicateContextImpl){ - //This will use cache for document ($) queries - PredicateContextImpl ctxi = (PredicateContextImpl) ctx; - expectedVal = ctxi.evaluate(expectedPath); - } else { - Object doc = expectedPath.isRootPath()?ctx.root():ctx.item(); - expectedVal = expectedPath.evaluate(doc, ctx.root(), ctx.configuration()).getValue(); - } - } + Object leftVal = evaluateIfPath(left, ctx); + Object rightVal = evaluateIfPath(right, ctx); - return criteriaType.eval(expectedVal, actual, ctx); + return criteriaType.eval(rightVal, leftVal, ctx); } catch (ValueCompareException e) { return false; } catch (PathNotFoundException e) { @@ -374,6 +381,9 @@ public class Criteria implements Predicate { */ public static Criteria where(String key) { + if(!key.startsWith("$") && !key.startsWith("@")){ + key = "@." + key; + } return where(PathCompiler.compile(key)); } @@ -384,6 +394,9 @@ public class Criteria implements Predicate { * @return the criteria builder */ public Criteria and(String key) { + if(!key.startsWith("$") && !key.startsWith("@")){ + key = "@." + key; + } return new Criteria(this.criteriaChain, PathCompiler.compile(key)); } @@ -395,7 +408,7 @@ public class Criteria implements Predicate { */ public Criteria is(Object o) { this.criteriaType = CriteriaType.EQ; - this.expected = o; + this.right = o; return this; } @@ -417,7 +430,7 @@ public class Criteria implements Predicate { */ public Criteria ne(Object o) { this.criteriaType = CriteriaType.NE; - this.expected = o; + this.right = o; return this; } @@ -429,7 +442,7 @@ public class Criteria implements Predicate { */ public Criteria lt(Object o) { this.criteriaType = CriteriaType.LT; - this.expected = o; + this.right = o; return this; } @@ -441,7 +454,7 @@ public class Criteria implements Predicate { */ public Criteria lte(Object o) { this.criteriaType = CriteriaType.LTE; - this.expected = o; + this.right = o; return this; } @@ -453,7 +466,7 @@ public class Criteria implements Predicate { */ public Criteria gt(Object o) { this.criteriaType = CriteriaType.GT; - this.expected = o; + this.right = o; return this; } @@ -465,7 +478,7 @@ public class Criteria implements Predicate { */ public Criteria gte(Object o) { this.criteriaType = CriteriaType.GTE; - this.expected = o; + this.right = o; return this; } @@ -478,7 +491,7 @@ public class Criteria implements Predicate { public Criteria regex(Pattern pattern) { notNull(pattern, "pattern can not be null"); this.criteriaType = CriteriaType.REGEX; - this.expected = pattern; + this.right = pattern; return this; } @@ -503,7 +516,7 @@ public class Criteria implements Predicate { public Criteria in(Collection c) { notNull(c, "collection can not be null"); this.criteriaType = CriteriaType.IN; - this.expected = c; + this.right = c; return this; } @@ -528,7 +541,7 @@ public class Criteria implements Predicate { public Criteria nin(Collection c) { notNull(c, "collection can not be null"); this.criteriaType = CriteriaType.NIN; - this.expected = c; + this.right = c; return this; } @@ -553,7 +566,7 @@ public class Criteria implements Predicate { public Criteria all(Collection c) { notNull(c, "collection can not be null"); this.criteriaType = CriteriaType.ALL; - this.expected = c; + this.right = c; return this; } @@ -570,7 +583,7 @@ public class Criteria implements Predicate { */ public Criteria size(int size) { this.criteriaType = CriteriaType.SIZE; - this.expected = size; + this.right = size; return this; } @@ -583,7 +596,7 @@ public class Criteria implements Predicate { */ public Criteria exists(boolean b) { this.criteriaType = CriteriaType.EXISTS; - this.expected = b; + this.right = b; return this; } @@ -596,7 +609,7 @@ public class Criteria implements Predicate { public Criteria type(Class t) { notNull(t, "type can not be null"); this.criteriaType = CriteriaType.TYPE; - this.expected = t; + this.right = t; return this; } @@ -607,7 +620,7 @@ public class Criteria implements Predicate { */ public Criteria notEmpty() { this.criteriaType = CriteriaType.NOT_EMPTY; - this.expected = null; + this.right = null; return this; } @@ -619,73 +632,115 @@ public class Criteria implements Predicate { */ public Criteria matches(Predicate p) { this.criteriaType = CriteriaType.MATCHES; - this.expected = p; + this.right = p; return this; } + private static boolean isPath(String string){ + return (string != null && (string.startsWith("$") || string.startsWith("@"))); + } + private static boolean isString(String string){ + return (string != null && !string.isEmpty() && string.charAt(0) == '\'' && string.charAt(string.length() - 1) == '\''); + } + + + /** + * Parse the provided criteria + * @param criteria + * @return a criteria + */ + public static Criteria parse(String criteria){ + int operatorIndex = -1; + String left = ""; + String operator = ""; + String right = ""; + for (int y = 0; y < OPERATORS.length; y++) { + operatorIndex = criteria.indexOf(OPERATORS[y]); + if (operatorIndex != -1) { + operator = OPERATORS[y]; + break; + } + } + if (!operator.isEmpty()) { + left = criteria.substring(0, operatorIndex).trim(); + right = criteria.substring(operatorIndex + operator.length()).trim(); + } else { + left = criteria.trim(); + } + return Criteria.create(left, operator, right); + } + /** * Creates a new criteria - * @param path path to evaluate in criteria + * @param left path to evaluate in criteria * @param operator operator - * @param expected expected value + * @param right expected value * @return a new Criteria */ - public static Criteria create(String path, String operator, String expected) { - if (!expected.isEmpty() && expected.charAt(0) == '\'' && expected.charAt(expected.length() - 1) == '\'') { - expected = expected.substring(1, expected.length() - 1); + public static Criteria create(String left, String operator, String right) { + Object leftPrepared = left; + Object rightPrepared = right; + Path leftPath = null; + Path rightPath = null; + + if(isPath(left)){ + leftPath = PathCompiler.compile(left); + if(!leftPath.isDefinite()){ + throw new InvalidPathException("the predicate path: " + left + " is not definite"); + } + leftPrepared = leftPath; + } else if(isString(left)) { + leftPrepared = left.substring(1, left.length() - 1); } - Path p = PathCompiler.compile(path); - - if (("$".equals(path) || "@".equals(path) )&& (operator == null || operator.isEmpty()) && (expected == null || expected.isEmpty())) { - return new Criteria(p, CriteriaType.NE, null); - } else if (operator.isEmpty()) { - return Criteria.where(path).exists(true); - } else { - if(expected.startsWith("$") || expected.startsWith("@")){ - Path compile = PathCompiler.compile(expected); - if(!compile.isDefinite()){ - throw new InvalidPathException("the predicate path: " + expected + " is not definite"); - } - return new Criteria(p, CriteriaType.parse(operator), compile); - } else { - return new Criteria(p, CriteriaType.parse(operator), expected); + if(isPath(right)){ + rightPath = PathCompiler.compile(right); + if(!rightPath.isDefinite()){ + throw new InvalidPathException("the predicate path: " + right + " is not definite"); } + rightPrepared = rightPath; + } else if(isString(right)) { + rightPrepared = right.substring(1, right.length() - 1); + } + if(leftPath != null && operator.isEmpty()){ + return Criteria.where(leftPath).exists(true); + } else { + return new Criteria(leftPrepared, CriteriaType.parse(operator), rightPrepared); } } - private static int safeCompare(Object expected, Object providerParsed) throws ValueCompareException { + private static int safeCompare(Object left, Object right) throws ValueCompareException { - if(expected == providerParsed){ + if(left == right){ return 0; } - boolean expNullish = isNullish(expected); - boolean provNullish = isNullish(providerParsed); + boolean leftNullish = isNullish(left); + boolean rightNullish = isNullish(right); - if (expNullish && !provNullish) { + if (leftNullish && !rightNullish) { return -1; - } else if (!expNullish && provNullish) { + } else if (!leftNullish && rightNullish) { return 1; - } else if (expNullish && provNullish) { + } else if (leftNullish && rightNullish) { return 0; - } else if (expected instanceof String && providerParsed instanceof String) { - return ((String) expected).compareTo((String) providerParsed); - } else if (expected instanceof Number && providerParsed instanceof Number) { - return new BigDecimal(expected.toString()).compareTo(new BigDecimal(providerParsed.toString())); - } else if (expected instanceof String && providerParsed instanceof Number) { - return new BigDecimal(expected.toString()).compareTo(new BigDecimal(providerParsed.toString())); - } else if (expected instanceof String && providerParsed instanceof Boolean) { - Boolean e = Boolean.valueOf((String) expected); - Boolean a = (Boolean) providerParsed; + } else if (left instanceof String && right instanceof String) { + return ((String) left).compareTo((String) right); + } else if (left instanceof Number && right instanceof Number) { + return new BigDecimal(left.toString()).compareTo(new BigDecimal(right.toString())); + } else if (left instanceof String && right instanceof Number) { + return new BigDecimal(left.toString()).compareTo(new BigDecimal(right.toString())); + } else if (left instanceof String && right instanceof Boolean) { + Boolean e = Boolean.valueOf((String) left); + Boolean a = (Boolean) right; return e.compareTo(a); - } else if (expected instanceof Boolean && providerParsed instanceof Boolean) { - Boolean e = (Boolean) expected; - Boolean a = (Boolean) providerParsed; + } else if (left instanceof Boolean && right instanceof Boolean) { + Boolean e = (Boolean) left; + Boolean a = (Boolean) right; return e.compareTo(a); } else { - logger.debug("Can not compare a {} with a {}", expected.getClass().getName(), providerParsed.getClass().getName()); + logger.debug("Can not compare a {} with a {}", left.getClass().getName(), right.getClass().getName()); throw new ValueCompareException(); } } @@ -699,16 +754,16 @@ public class Criteria implements Predicate { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append(path.toString()) + sb.append(left.toString()) //.append("|") .append(criteriaType.toString()) //.append("|") - .append(wrapString(expected)); + .append(wrapString(right)); //.append("|"); return sb.toString(); } - private String wrapString(Object o){ + private static String wrapString(Object o){ if(o == null){ return "null"; } @@ -721,25 +776,5 @@ public class Criteria implements Predicate { - public static Criteria parse(String criteria){ - int operatorIndex = -1; - String left = ""; - String operator = ""; - String right = ""; - for (int y = 0; y < OPERATORS.length; y++) { - operatorIndex = criteria.indexOf(OPERATORS[y]); - if (operatorIndex != -1) { - operator = OPERATORS[y]; - break; - } - } - if (!operator.isEmpty()) { - left = criteria.substring(0, operatorIndex).trim(); - right = criteria.substring(operatorIndex + operator.length()).trim(); - } else { - left = criteria.trim(); - } - return Criteria.create(left, operator, right); - } } diff --git a/json-path/src/test/java/com/jayway/jsonpath/InlineFilterTest.java b/json-path/src/test/java/com/jayway/jsonpath/InlineFilterTest.java index 38bb4b25..3a38610e 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/InlineFilterTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/InlineFilterTest.java @@ -75,4 +75,38 @@ public class InlineFilterTest extends BaseTest { List h = reader.read("$.store.book[?(@.display-price == 8.95 || @.display-price == 8.99 || (@.display-price == 22.99 && @.category == 'reference') )].author", List.class); assertThat(h).containsOnly("Nigel Rees", "Herman Melville"); } + + @Test + public void no_path_ref_in_filter_hit_all() { + + List res = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?('a' == 'a')].author"); + + assertThat(res).containsExactly("Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"); + + } + + @Test + public void no_path_ref_in_filter_hit_none() { + + List res = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?('a' == 'b')].author"); + + assertThat(res).isEmpty(); + + } + + @Test + public void path_can_be_on_either_side_of_operator() { + List resLeft = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?(@.category == 'reference')].author"); + List resRight = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?('reference' == @.category)].author"); + + assertThat(resLeft).containsExactly("Nigel Rees"); + assertThat(resRight).containsExactly("Nigel Rees"); + } + + @Test + public void path_can_be_on_both_side_of_operator() { + List res = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?(@.category == @.category)].author"); + + assertThat(res).containsExactly("Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"); + } } diff --git a/json-path/src/test/java/com/jayway/jsonpath/old/FilterTest.java b/json-path/src/test/java/com/jayway/jsonpath/old/FilterTest.java index e34b5b7c..66a43f4f 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/old/FilterTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/old/FilterTest.java @@ -275,9 +275,9 @@ public class FilterTest extends BaseTest { JsonPath.parse(json).json(); - assertThat((String)JsonPath.read(jocksInTexas1, "[0].address.state"), is("Texas")); - assertThat((String)JsonPath.read(jocksInTexas1, "[0].first-name"), is("Jock")); - assertThat((String)JsonPath.read(jocksInTexas1, "[0].last-name"), is("Ewing")); + assertThat((String)JsonPath.read(jocksInTexas1, "$[0].address.state"), is("Texas")); + assertThat((String)JsonPath.read(jocksInTexas1, "$[0].first-name"), is("Jock")); + assertThat((String)JsonPath.read(jocksInTexas1, "$[0].last-name"), is("Ewing")); }