diff --git a/README.md b/README.md index 71030e06..caaf9a2d 100644 --- a/README.md +++ b/README.md @@ -193,7 +193,8 @@ Inline predicates are the ones defined in the path. List> books = JsonPath.parse(json).read("$.store.book[?(@.price < 10)]"); ``` -In the current implementation you can use `&&` to combine multiple predicates `[?(@.price < 10 && @.category == 'fiction')]`. OR operations are not supported yet. +In the current implementation you can use `&&` to combine multiple predicates `[?(@.price < 10 && @.category == 'fiction')]`. +OR operations are not supported in inline predicates yet. ###The Filter API @@ -214,6 +215,12 @@ List> books = parse(json).read("$.store.book[?]", cheapFict Notice the placeholder `?` for the filter in the path. When multiple filters are provided they are applied in order where the number of placeholders must match the number of provided filters. You can specify multiple predicate placeholders in one filter operation `[?, ?]`, both predicates must match. +Filters can also be combined with 'OR' and 'AND' +```java +Filter fooOrBar = filter(where("foo").exists(true)).or(where("bar").exists(true)); +Filter fooAndBar = filter(where("foo").exists(true)).and(where("bar").exists(true)); +``` + ###Roll Your Own Third option is to implement your own predicates diff --git a/json-path/src/main/java/com/jayway/jsonpath/Filter.java b/json-path/src/main/java/com/jayway/jsonpath/Filter.java index 8b8f397d..74d67cce 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/Filter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/Filter.java @@ -3,12 +3,17 @@ package com.jayway.jsonpath; import java.util.ArrayList; import java.util.List; +import static java.util.Arrays.asList; + /** * */ public class Filter implements Predicate { - private List criteriaList = new ArrayList(); + protected List criteriaList = new ArrayList(); + + private Filter() { + } private Filter(Predicate criteria) { this.criteriaList.add(criteria); @@ -18,6 +23,8 @@ public class Filter implements Predicate { this.criteriaList = criteriaList; } + + /** * Creates a new Filter based on given criteria * @param criteria criteria @@ -54,4 +61,26 @@ public class Filter implements Predicate { } return sb.toString(); } + + public Filter or(final Predicate other){ + return new Filter(){ + @Override + public boolean apply(PredicateContext ctx) { + boolean a = Filter.this.apply(ctx); + boolean b = other.apply(ctx); + return a || b; + } + }; + } + + public Filter and(final Predicate other){ + return new Filter(){ + @Override + public boolean apply(PredicateContext ctx) { + boolean a = Filter.this.apply(ctx); + boolean b = other.apply(ctx); + return a && b; + } + }; + } } diff --git a/json-path/src/test/java/com/jayway/jsonpath/FilterTest.java b/json-path/src/test/java/com/jayway/jsonpath/FilterTest.java index 0bdc8b39..4e2a2900 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/FilterTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/FilterTest.java @@ -2,6 +2,7 @@ package com.jayway.jsonpath; import org.junit.Test; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; @@ -385,4 +386,28 @@ public class FilterTest extends BaseTest { }; assertThat(filter(where("string-key").eq("string").and("$").matches(p)).apply(createPredicateContext(json))).isEqualTo(true); } + + //---------------------------------------------------------------------------- + // + // OR + // + //---------------------------------------------------------------------------- + @Test + public void or_and_filters_evaluates() { + + Map model = new HashMap(); + model.put("foo", true); + model.put("bar", false); + + Filter isFoo = filter(where("foo").is(true)); + Filter isBar = filter(where("bar").is(true)); + + + Filter fooOrBar = filter(where("foo").exists(true)).or(where("bar").exists(true)); + Filter fooAndBar = filter(where("foo").exists(true)).and(where("bar").exists(true)); + + assertThat(isFoo.or(isBar).apply(createPredicateContext(model))).isTrue(); + assertThat(isFoo.and(isBar).apply(createPredicateContext(model))).isFalse(); + + } } diff --git a/json-path/src/test/java/com/jayway/jsonpath/PredicateTest.java b/json-path/src/test/java/com/jayway/jsonpath/PredicateTest.java index b4f53cb9..62939070 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/PredicateTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/PredicateTest.java @@ -14,7 +14,6 @@ public class PredicateTest extends BaseTest { @Test public void predicates_filters_can_be_applied() { - Predicate booksWithISBN = new Predicate() { @Override public boolean apply(PredicateContext ctx) { @@ -23,7 +22,5 @@ public class PredicateTest extends BaseTest { }; assertThat(reader.read("$.store.book[?].isbn", List.class, booksWithISBN)).containsOnly("0-395-19395-8", "0-553-21311-3"); - - } }