Browse Source

Merge pull request #283 from arifogel/master

Implement boolean negation '!' operator for filter expressions
pull/320/head
kallestenflo 7 years ago committed by GitHub
parent
commit
c946c66506
  1. 2
      README.md
  2. 15
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java
  3. 10
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/LogicalExpressionNode.java
  4. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/LogicalOperator.java

2
README.md

@ -256,6 +256,8 @@ List<Map<String, Object>> books = JsonPath.parse(json)
You can use `&&` and `||` to combine multiple predicates `[?(@.price < 10 && @.category == 'fiction')]` , You can use `&&` and `||` to combine multiple predicates `[?(@.price < 10 && @.category == 'fiction')]` ,
`[?(@.category == 'reference' || @.price > 10)]`. `[?(@.category == 'reference' || @.price > 10)]`.
You can use `!` to negate a predicate `[?(!(@.price < 10 && @.category == 'fiction'))]`.
###Filter Predicates ###Filter Predicates
Predicates can be built using the Filter API as shown below: Predicates can be built using the Filter API as shown below:

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

@ -120,7 +120,7 @@ public class FilterCompiler {
/* /*
* LogicalOR = LogicalAND { '||' LogicalAND } * LogicalOR = LogicalAND { '||' LogicalAND }
* LogicalAND = LogicalANDOperand { '&&' LogicalANDOperand } * LogicalAND = LogicalANDOperand { '&&' LogicalANDOperand }
* LogicalANDOperand = RelationalExpression | '(' LogicalOR ')' * LogicalANDOperand = RelationalExpression | '(' LogicalOR ')' | '!' LogicalANDOperand
* RelationalExpression = Value [ RelationalOperator Value ] * RelationalExpression = Value [ RelationalOperator Value ]
*/ */
@ -164,6 +164,19 @@ public class FilterCompiler {
} }
private ExpressionNode readLogicalANDOperand() { private ExpressionNode readLogicalANDOperand() {
int savepoint = filter.skipBlanks().position();
if (filter.skipBlanks().currentCharIs(NOT)) {
filter.readSignificantChar(NOT);
switch (filter.skipBlanks().currentChar()) {
case DOC_CONTEXT:
case EVAL_CONTEXT:
filter.setPosition(savepoint);
break;
default:
final ExpressionNode op = readLogicalANDOperand();
return LogicalExpressionNode.createLogicalNot(op);
}
}
if (filter.skipBlanks().currentCharIs(OPEN_PARENTHESIS)) { if (filter.skipBlanks().currentCharIs(OPEN_PARENTHESIS)) {
filter.readSignificantChar(OPEN_PARENTHESIS); filter.readSignificantChar(OPEN_PARENTHESIS);
final ExpressionNode op = readLogicalOR(); final ExpressionNode op = readLogicalOR();

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

@ -10,6 +10,10 @@ public class LogicalExpressionNode extends ExpressionNode {
protected List<ExpressionNode> chain = new ArrayList<ExpressionNode>(); protected List<ExpressionNode> chain = new ArrayList<ExpressionNode>();
private final LogicalOperator operator; private final LogicalOperator operator;
public static ExpressionNode createLogicalNot(ExpressionNode op) {
return new LogicalExpressionNode(op, LogicalOperator.NOT, null);
}
public static LogicalExpressionNode createLogicalOr(ExpressionNode left,ExpressionNode right){ public static LogicalExpressionNode createLogicalOr(ExpressionNode left,ExpressionNode right){
return new LogicalExpressionNode(left, LogicalOperator.OR, right); return new LogicalExpressionNode(left, LogicalOperator.OR, right);
} }
@ -68,13 +72,17 @@ public class LogicalExpressionNode extends ExpressionNode {
} }
} }
return false; return false;
} else { } else if (operator == LogicalOperator.AND) {
for (ExpressionNode expression : chain) { for (ExpressionNode expression : chain) {
if(!expression.apply(ctx)){ if(!expression.apply(ctx)){
return false; return false;
} }
} }
return true; return true;
} else {
ExpressionNode expression = chain.get(0);
return !expression.apply(ctx);
} }
} }
} }

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

@ -5,6 +5,7 @@ import com.jayway.jsonpath.InvalidPathException;
public enum LogicalOperator { public enum LogicalOperator {
AND("&&"), AND("&&"),
NOT("!"),
OR("||"); OR("||");
private final String operatorString; private final String operatorString;
@ -24,6 +25,7 @@ public enum LogicalOperator {
public static LogicalOperator fromString(String operatorString){ public static LogicalOperator fromString(String operatorString){
if(AND.operatorString.equals(operatorString)) return AND; if(AND.operatorString.equals(operatorString)) return AND;
else if(NOT.operatorString.equals(operatorString)) return NOT;
else if(OR.operatorString.equals(operatorString)) return OR; else if(OR.operatorString.equals(operatorString)) return OR;
else throw new InvalidPathException("Failed to parse operator " + operatorString); else throw new InvalidPathException("Failed to parse operator " + operatorString);
} }

Loading…
Cancel
Save