Browse Source

Negate exist checks in inline filters (not defined or null)

parse(JSON_DOCUMENT).read("$.store.book[?(!@.isbn)]")
pull/60/head
Kalle Stenflo 10 years ago
parent
commit
290edb540c
  1. 2
      changelog.md
  2. 22
      json-path/src/main/java/com/jayway/jsonpath/Criteria.java
  3. 28
      json-path/src/test/java/com/jayway/jsonpath/InlineFilterTest.java
  4. 5
      json-path/src/test/java/com/jayway/jsonpath/old/FilterTest.java

2
changelog.md

@ -16,6 +16,8 @@ In The Pipe
* Inline filter does not force path first
`parse(JSON_DOCUMENT).read("$.store.book[?(@.category == 'reference')].author")`
`parse(JSON_DOCUMENT).read("$.store.book[?('reference' == @.category)].author")`
* Negate exist checks in inline filters (not defined or null)
`parse(JSON_DOCUMENT).read("$.store.book[?(!@.isbn)]")`
1.1.0 (2014-10-01)

22
json-path/src/main/java/com/jayway/jsonpath/Criteria.java

@ -360,8 +360,13 @@ public class Criteria implements Predicate {
boolean exists = ((Boolean) right);
try {
Configuration c = Configuration.builder().jsonProvider(ctx.configuration().jsonProvider()).options(Option.REQUIRE_PROPERTIES).build();
((Path)left).evaluate(ctx.item(), ctx.root(), c).getValue();
return exists;
Object value = ((Path) left).evaluate(ctx.item(), ctx.root(), c).getValue();
if(exists){
return (value != null);
} else {
return (value == null);
}
} catch (PathNotFoundException e) {
return !exists;
}
@ -654,7 +659,8 @@ public class Criteria implements Predicate {
}
private static boolean isPath(String string){
return (string != null && (string.startsWith("$") || string.startsWith("@")));
return (string != null
&& (string.startsWith("$") || string.startsWith("@") || string.startsWith("!@")));
}
private static boolean isString(String string){
@ -717,8 +723,13 @@ public class Criteria implements Predicate {
Object rightPrepared = right;
Path leftPath = null;
Path rightPath = null;
boolean existsCheck = true;
if(isPath(left)){
if(left.charAt(0) == '!'){
existsCheck = false;
left = left.substring(1);
}
leftPath = PathCompiler.compile(left);
if(!leftPath.isDefinite()){
throw new InvalidPathException("the predicate path: " + left + " is not definite");
@ -731,6 +742,9 @@ public class Criteria implements Predicate {
}
if(isPath(right)){
if(right.charAt(0) == '!'){
throw new InvalidPathException("Invalid negation! Can only be used for existence check e.g [?(!@.foo)]");
}
rightPath = PathCompiler.compile(right);
if(!rightPath.isDefinite()){
throw new InvalidPathException("the predicate path: " + right + " is not definite");
@ -743,7 +757,7 @@ public class Criteria implements Predicate {
}
if(leftPath != null && operator.isEmpty()){
return Criteria.where(leftPath).exists(true);
return Criteria.where(leftPath).exists(existsCheck);
} else {
return new Criteria(leftPrepared, CriteriaType.parse(operator), rightPrepared);
}

28
json-path/src/test/java/com/jayway/jsonpath/InlineFilterTest.java

@ -2,6 +2,7 @@ package com.jayway.jsonpath;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static java.util.Arrays.asList;
@ -129,4 +130,31 @@ public class InlineFilterTest extends BaseTest {
resLeft = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?(@.category =~ /REFERENCE/i)].author");
assertThat(resLeft).containsExactly("Nigel Rees");
}
@Test
public void negate_exists_check() {
List<String> hasIsbn = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?(@.isbn)].author");
assertThat(hasIsbn).containsExactly("Herman Melville", "J. R. R. Tolkien");
List<String> noIsbn = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?(!@.isbn)].author");
assertThat(noIsbn).containsExactly("Nigel Rees", "Evelyn Waugh");
}
@Test
public void negate_exists_check_primitive() {
List<Integer> ints = new ArrayList<Integer>();
ints.add(0);
ints.add(1);
ints.add(null);
ints.add(2);
ints.add(3);
List<Integer> notNull = JsonPath.parse(ints).read("$[?(@)]");
assertThat(notNull).containsExactly(0,1,2,3);
List<Integer> isNull = JsonPath.parse(ints).read("$[?(!@)]");
assertThat(isNull).containsExactly(new Integer[]{null});
}
}

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

@ -191,7 +191,6 @@ public class FilterTest extends BaseTest {
}
@Test
//@Ignore //TODO: finalize behaviour
public void exists_filters_evaluates() throws Exception {
Map<String, Object> check = new HashMap<String, Object>();
check.put("foo", "foo");
@ -200,8 +199,8 @@ public class FilterTest extends BaseTest {
assertTrue(filter(where("foo").exists(true)).apply(createPredicateContext(check)));
assertFalse(filter(where("foo").exists(false)).apply(createPredicateContext(check)));
assertTrue(filter(where("foo_null").exists(true)).apply(createPredicateContext(check)));
assertFalse(filter(where("foo_null").exists(false)).apply(createPredicateContext(check)));
assertTrue(filter(where("foo_null").exists(false)).apply(createPredicateContext(check)));
assertFalse(filter(where("foo_null").exists(true)).apply(createPredicateContext(check)));
assertTrue(filter(where("bar").exists(false)).apply(createPredicateContext(check)));
assertFalse(filter(where("bar").exists(true)).apply(createPredicateContext(check)));

Loading…
Cancel
Save