Browse Source

implement subset filter operator, update readme

pull/365/head
Ari Fogel 8 years ago committed by Daniel Halperin
parent
commit
32adc12c9c
  1. 1
      README.md
  2. 27
      json-path/src/main/java/com/jayway/jsonpath/Criteria.java
  3. 31
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java
  4. 3
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/RelationalOperator.java
  5. 9
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java

1
README.md

@ -101,6 +101,7 @@ Filters are logical expressions used to filter arrays. A typical filter would be
| =~ | left matches regular expression [?(@.name =~ /foo.*?/i)] |
| in | left exists in right [?(@.size in ['S', 'M'])] |
| nin | left does not exists in right |
| subset | left is a subset of right [?(@.sizes subset ['S', 'M', 'L'])] |
| size | size of left (array or string) should match right |
| empty | left (array or string) should be empty |

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

@ -267,6 +267,33 @@ public class Criteria implements Predicate {
return this;
}
/**
* The <code>subset</code> operator selects objects for which the specified field is
* an array whose elements comprise a subset of the set comprised by the elements of
* the specified array.
*
* @param o the values to match against
* @return the criteria
*/
public Criteria subset(Object... o) {
return subset(Arrays.asList(o));
}
/**
* The <code>subset</code> operator selects objects for which the specified field is
* an array whose elements comprise a subset of the set comprised by the elements of
* the specified array.
*
* @param c the values to match against
* @return the criteria
*/
public Criteria subset(Collection<?> c) {
notNull(c, "collection can not be null");
this.criteriaType = RelationalOperator.SUBSET;
this.right = new ValueNode.ValueListNode(c);
return this;
}
/**
* The <code>all</code> operator is similar to $in, but instead of matching any value
* in the specified array all values in the array must be matched.

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

@ -29,6 +29,7 @@ public class EvaluatorFactory {
evaluators.put(RelationalOperator.CONTAINS, new ContainsEvaluator());
evaluators.put(RelationalOperator.MATCHES, new PredicateMatchEvaluator());
evaluators.put(RelationalOperator.TYPE, new TypeEvaluator());
evaluators.put(RelationalOperator.SUBSET, new SubsetEvaluator());
}
public static Evaluator createEvaluator(RelationalOperator operator){
@ -264,4 +265,34 @@ public class EvaluatorFactory {
return input;
}
}
private static class SubsetEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
ValueNode.ValueListNode rightValueListNode;
if(right.isJsonNode()){
ValueNode vn = right.asJsonNode().asValueListNode(ctx);
if(vn.isUndefinedNode()){
return false;
} else {
rightValueListNode = vn.asValueListNode();
}
} else {
rightValueListNode = right.asValueListNode();
}
ValueNode.ValueListNode leftValueListNode;
if(left.isJsonNode()){
ValueNode vn = left.asJsonNode().asValueListNode(ctx);
if(vn.isUndefinedNode()){
return false;
} else {
leftValueListNode = vn.asValueListNode();
}
} else {
leftValueListNode = left.asValueListNode();
}
return leftValueListNode.subset(rightValueListNode);
}
}
}

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

@ -29,7 +29,8 @@ public enum RelationalOperator {
EXISTS("EXISTS"),
TYPE("TYPE"),
MATCHES("MATCHES"),
EMPTY("EMPTY");
EMPTY("EMPTY"),
SUBSET("SUBSET");
private final String operatorString;

9
json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java

@ -714,6 +714,15 @@ public abstract class ValueNode {
return nodes.contains(node);
}
public boolean subset(ValueListNode right) {
for (ValueNode leftNode : nodes) {
if (!right.nodes.contains(leftNode)) {
return false;
}
}
return true;
}
public List<ValueNode> getNodes() {
return Collections.unmodifiableList(nodes);
}

Loading…
Cancel
Save