Skip to content

Commit 32adc12

Browse files
arifogeldhalperi
authored andcommitted
implement subset filter operator, update readme
1 parent 720cf09 commit 32adc12

File tree

5 files changed

+70
-1
lines changed

5 files changed

+70
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ Filters are logical expressions used to filter arrays. A typical filter would be
101101
| =~ | left matches regular expression [?(@.name =~ /foo.*?/i)] |
102102
| in | left exists in right [?(@.size in ['S', 'M'])] |
103103
| nin | left does not exists in right |
104+
| subset | left is a subset of right [?(@.sizes subset ['S', 'M', 'L'])] |
104105
| size | size of left (array or string) should match right |
105106
| empty | left (array or string) should be empty |
106107

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,33 @@ public Criteria nin(Collection<?> c) {
267267
return this;
268268
}
269269

270+
/**
271+
* The <code>subset</code> operator selects objects for which the specified field is
272+
* an array whose elements comprise a subset of the set comprised by the elements of
273+
* the specified array.
274+
*
275+
* @param o the values to match against
276+
* @return the criteria
277+
*/
278+
public Criteria subset(Object... o) {
279+
return subset(Arrays.asList(o));
280+
}
281+
282+
/**
283+
* The <code>subset</code> operator selects objects for which the specified field is
284+
* an array whose elements comprise a subset of the set comprised by the elements of
285+
* the specified array.
286+
*
287+
* @param c the values to match against
288+
* @return the criteria
289+
*/
290+
public Criteria subset(Collection<?> c) {
291+
notNull(c, "collection can not be null");
292+
this.criteriaType = RelationalOperator.SUBSET;
293+
this.right = new ValueNode.ValueListNode(c);
294+
return this;
295+
}
296+
270297
/**
271298
* The <code>all</code> operator is similar to $in, but instead of matching any value
272299
* in the specified array all values in the array must be matched.

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class EvaluatorFactory {
2929
evaluators.put(RelationalOperator.CONTAINS, new ContainsEvaluator());
3030
evaluators.put(RelationalOperator.MATCHES, new PredicateMatchEvaluator());
3131
evaluators.put(RelationalOperator.TYPE, new TypeEvaluator());
32+
evaluators.put(RelationalOperator.SUBSET, new SubsetEvaluator());
3233
}
3334

3435
public static Evaluator createEvaluator(RelationalOperator operator){
@@ -264,4 +265,34 @@ private String getInput(ValueNode valueNode) {
264265
return input;
265266
}
266267
}
268+
269+
private static class SubsetEvaluator implements Evaluator {
270+
@Override
271+
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
272+
ValueNode.ValueListNode rightValueListNode;
273+
if(right.isJsonNode()){
274+
ValueNode vn = right.asJsonNode().asValueListNode(ctx);
275+
if(vn.isUndefinedNode()){
276+
return false;
277+
} else {
278+
rightValueListNode = vn.asValueListNode();
279+
}
280+
} else {
281+
rightValueListNode = right.asValueListNode();
282+
}
283+
ValueNode.ValueListNode leftValueListNode;
284+
if(left.isJsonNode()){
285+
ValueNode vn = left.asJsonNode().asValueListNode(ctx);
286+
if(vn.isUndefinedNode()){
287+
return false;
288+
} else {
289+
leftValueListNode = vn.asValueListNode();
290+
}
291+
} else {
292+
leftValueListNode = left.asValueListNode();
293+
}
294+
return leftValueListNode.subset(rightValueListNode);
295+
}
296+
}
297+
267298
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ public enum RelationalOperator {
2929
EXISTS("EXISTS"),
3030
TYPE("TYPE"),
3131
MATCHES("MATCHES"),
32-
EMPTY("EMPTY");
32+
EMPTY("EMPTY"),
33+
SUBSET("SUBSET");
3334

3435
private final String operatorString;
3536

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,15 @@ public boolean contains(ValueNode node){
714714
return nodes.contains(node);
715715
}
716716

717+
public boolean subset(ValueListNode right) {
718+
for (ValueNode leftNode : nodes) {
719+
if (!right.nodes.contains(leftNode)) {
720+
return false;
721+
}
722+
}
723+
return true;
724+
}
725+
717726
public List<ValueNode> getNodes() {
718727
return Collections.unmodifiableList(nodes);
719728
}

0 commit comments

Comments
 (0)