Browse Source

Support null filters like [?(@foo == null)] and [?(@foo != null)]

pull/31/merge
Kalle Stenflo 11 years ago
parent
commit
410e4269c7
  1. 28
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/eval/ExpressionEvaluator.java
  2. 84
      json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java

28
json-path/src/main/java/com/jayway/jsonpath/internal/filter/eval/ExpressionEvaluator.java

@ -25,9 +25,16 @@ import java.util.Map;
*/ */
public class ExpressionEvaluator { public class ExpressionEvaluator {
private static final String NULL_VALUE = "null";
public enum Operator { public enum Operator {
equal("=="), not_equal("!="), less_or_greater_than("<>"), greater_than(">"), greater_than_or_equal(">="), less_than("<"), less_than_or_equal("<="); equal("=="),
not_equal("!="),
less_or_greater_than("<>"), //same as not_equal
greater_than(">"),
greater_than_or_equal(">="),
less_than("<"),
less_than_or_equal("<=");
private final String representation; private final String representation;
@ -58,6 +65,21 @@ public class ExpressionEvaluator {
throw new IllegalArgumentException("Unsupported operator " + comparator); throw new IllegalArgumentException("Unsupported operator " + comparator);
} }
if(actual == null){
if(operator == Operator.equal){
return NULL_VALUE.equals(expected);
} else if(operator == Operator.not_equal || operator == Operator.less_or_greater_than){
return !NULL_VALUE.equals(expected);
}
} else {
if(operator == Operator.not_equal || operator == Operator.less_or_greater_than){
if(NULL_VALUE.equals(expected)){
return true;
}
}
}
if (actual instanceof Long) { if (actual instanceof Long) {
Long a = (Long) actual; Long a = (Long) actual;
@ -173,7 +195,7 @@ public class ExpressionEvaluator {
BigInteger a = (BigInteger) actual; BigInteger a = (BigInteger) actual;
BigInteger e = new BigInteger(expected.trim()); BigInteger e = new BigInteger(expected.trim());
switch (operator){ switch (operator) {
case equal: case equal:
return a.compareTo(e) == 0; return a.compareTo(e) == 0;
case not_equal: case not_equal:
@ -196,7 +218,7 @@ public class ExpressionEvaluator {
BigDecimal a = (BigDecimal) actual; BigDecimal a = (BigDecimal) actual;
BigDecimal e = new BigDecimal(expected); BigDecimal e = new BigDecimal(expected);
switch (operator){ switch (operator) {
case equal: case equal:
return a.compareTo(e) == 0; return a.compareTo(e) == 0;
case not_equal: case not_equal:

84
json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java

@ -6,7 +6,10 @@ import org.junit.Test;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@ -18,6 +21,51 @@ import static org.junit.Assert.assertTrue;
*/ */
public class ExpressionEvalTest { public class ExpressionEvalTest {
public static final String DOCUMENT= "{\n" +
" \"characters\": [\n" +
" {\n" +
" \"aliases\": [], \n" +
" \"name\": \"Kleeg Lars\", \n" +
" \"occupation\": \"Moisture farmer\", \n" +
" \"offspring\": []\n" +
" }, \n" +
" {\n" +
" \"aliases\": [], \n" +
" \"name\": \"Shmi Skywalker\", \n" +
" \"occupation\": \"Virgin mother\", \n" +
" \"offspring\": [\n" +
" \"AnakinSkywalker\"\n" +
" ]\n" +
" }, \n" +
" {\n" +
" \"aliases\": [\n" +
" \"Darth Vader\"\n" +
" ], \n" +
" \"name\": \"Annakin Skywalker\", \n" +
" \"occupation\": \"Hand of the Emperor, Lord of the Sith\", \n" +
" \"offspring\": [\n" +
" \"Luke Skywalker\", \n" +
" \"LeiaOrgana\"\n" +
" ]\n" +
" }, \n" +
" {\n" +
" \"aliases\": [\n" +
" \"Nerf herder\"\n" +
" ], \n" +
" \"name\": \"Luke Skywalker\", \n" +
" \"occupation\": \"Farm boy\", \n" +
" \"offspring\": null\n" +
" }, \n" +
" {\n" +
" \"aliases\": [\n" +
" \"Your Highness\"\n" +
" ], \n" +
" \"name\": \"Leia Organa\", \n" +
" \"occupation\": \"Senator\", \n" +
" }\n" +
" ]\n" +
"}\n";
@Test @Test
public void long_eval() throws Exception { public void long_eval() throws Exception {
@ -117,8 +165,42 @@ public class ExpressionEvalTest {
assertFalse(ExpressionEvaluator.eval(false, "==", "true")); assertFalse(ExpressionEvaluator.eval(false, "==", "true"));
assertFalse(ExpressionEvaluator.eval(true, "!=", "true")); assertFalse(ExpressionEvaluator.eval(true, "!=", "true"));
assertFalse(ExpressionEvaluator.eval(true, "<>", "true")); assertFalse(ExpressionEvaluator.eval(true, "<>", "true"));
assertFalse(ExpressionEvaluator.eval(false, "!=", "false"));
assertFalse(ExpressionEvaluator.eval(false, "<>", "false")); assertFalse(ExpressionEvaluator.eval(false, "<>", "false"));
assertFalse(ExpressionEvaluator.eval(false, "!=", "false"));
}
@Test
public void null_eval() throws Exception {
assertTrue(ExpressionEvaluator.eval(new Integer(10), "!=", "null"));
assertTrue(ExpressionEvaluator.eval(null, "==", "null"));
assertTrue(ExpressionEvaluator.eval(null, "<>", "FOO"));
assertTrue(ExpressionEvaluator.eval("FOO", "<>", "null"));
assertTrue(ExpressionEvaluator.eval(null, "!=", "FOO"));
assertTrue(ExpressionEvaluator.eval("FOO", "<>", "null"));
assertTrue(ExpressionEvaluator.eval(null, "!=", "10"));
}
@Test
public void nulls_filter() {
List<Map<String, Object>> result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring == null)]");
assertEquals(1, result.size());
result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring != null)]");
assertEquals(3, result.size());
result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring)]");
assertEquals(4, result.size());
} }

Loading…
Cancel
Save