Browse Source

Inline criteria handles path stmt on both sides of operator.

pull/59/head
Kalle Stenflo 10 years ago
parent
commit
ca4d18911e
  1. 2
      json-path-web-test/src/main/resources/webapp/index.html
  2. 369
      json-path/src/main/java/com/jayway/jsonpath/Criteria.java
  3. 34
      json-path/src/test/java/com/jayway/jsonpath/InlineFilterTest.java
  4. 6
      json-path/src/test/java/com/jayway/jsonpath/old/FilterTest.java

2
json-path-web-test/src/main/resources/webapp/index.html

@ -147,7 +147,7 @@
<div class="tab-pane active" id="jayway-tab">
<br/>
<a href="https://code.google.com/p/json-path/" target="_blank" style="float: right">About implementation...</a>
<a href="https://code.google.com/p/json-left/" target="_blank" style="float: right">About implementation...</a>
<span id="jayway-time"></span>&nbsp;millis
<hr/>
<div class="row">

369
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<Criteria> 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("[{}] {} [{}] => {}", "<NOT AN ARRAY>", 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<Criteria> criteriaChain, Path path) {
if (!path.isDefinite()) {
throw new InvalidCriteriaException("A criteria path must be definite. The path " + path.toString() + " is not!");
private Criteria(List<Criteria> 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<Criteria>(), path);
private Criteria(Object left) {
this(new LinkedList<Criteria>(), left);
}
private Criteria(Path path, CriteriaType criteriaType, Object expected) {
this(new LinkedList<Criteria>(), path);
private Criteria(Object left, CriteriaType criteriaType, Object right) {
this(new LinkedList<Criteria>(), 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;
Path p = PathCompiler.compile(path);
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);
}
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");
if(isPath(right)){
rightPath = PathCompiler.compile(right);
if(!rightPath.isDefinite()){
throw new InvalidPathException("the predicate path: " + right + " is not definite");
}
return new Criteria(p, CriteriaType.parse(operator), compile);
} else {
return new Criteria(p, CriteriaType.parse(operator), expected);
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);
}
}

34
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<String> 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<String> 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<String> resLeft = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?(@.category == 'reference')].author");
List<String> 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<String> res = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?(@.category == @.category)].author");
assertThat(res).containsExactly("Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien");
}
}

6
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"));
}

Loading…
Cancel
Save