From 9713976c8494a303032c495c7211821005a2ca68 Mon Sep 17 00:00:00 2001 From: Warwick Hunter Date: Sat, 30 Nov 2013 14:54:40 +1000 Subject: [PATCH] Implement the field exists check. This is the '@' token on the left hand side of '&&' in the expression below. $.menu.items[?(@ && @.id == 'ViewSVG')].id --- .../internal/filter/ArrayEvalFilter.java | 24 +++++++++++-------- .../com/jayway/jsonpath/ComplianceTest.java | 1 + 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java index 89ae7195..050989e4 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java @@ -30,7 +30,8 @@ import java.util.regex.Pattern; public class ArrayEvalFilter extends PathTokenFilter { private static final Pattern CONDITION_STATEMENT_PATTERN = Pattern.compile("\\[\\s?\\?\\(.*?[!=<>]+.*?\\)\\s?]"); - private static final Pattern PATTERN = Pattern.compile("\\s?(@.*?)\\s?([!=<>]+)\\s?(.*?)\\s?"); + private static final Pattern CONDITION_PATTERN = Pattern.compile("\\s?(@.*?)\\s?([!=<>]+)\\s?(.*?)\\s?"); + private static final Pattern FIELD_EXISTS_PATTERN = Pattern.compile("\\s?(@.*?)\\s?(.*?)\\s?"); @@ -86,7 +87,7 @@ public class ArrayEvalFilter extends PathTokenFilter { private boolean isMatch(Object check, Configuration configuration, ConditionStatement... conditionStatements) { try { for (ConditionStatement conditionStatement : conditionStatements) { - Object value = conditionStatement.path.read(check, configuration.options(Option.THROW_ON_MISSING_PROPERTY)); + Object value = (check != null) ? conditionStatement.path.read(check, configuration.options(Option.THROW_ON_MISSING_PROPERTY)) : null; boolean match = ExpressionEvaluator.eval(value, conditionStatement.getOperator(), conditionStatement.getExpected()); if(!match){ return false; @@ -105,16 +106,19 @@ public class ArrayEvalFilter extends PathTokenFilter { } static ConditionStatement createConditionStatement(String condition) { - Matcher matcher = PATTERN.matcher(condition); - if (matcher.matches()) { - String property = matcher.group(1).trim(); - String operator = matcher.group(2).trim(); - String expected = matcher.group(3).trim(); - + Matcher conditionMatcher = CONDITION_PATTERN.matcher(condition); + if (conditionMatcher.matches()) { + String property = conditionMatcher.group(1).trim(); + String operator = conditionMatcher.group(2).trim(); + String expected = conditionMatcher.group(3).trim(); return new ConditionStatement(condition, property, operator, expected); - } else { - return null; } + Matcher fieldExistsMatcher = FIELD_EXISTS_PATTERN.matcher(condition); + if (fieldExistsMatcher.matches()) { + // Field exists check, the single '@' in: $.menu.items[?(@ && @.id == 'ViewSVG')].id + return new ConditionStatement(condition, "@.", "!=", "null"); + } + return null; } static class ConditionStatement { diff --git a/json-path/src/test/java/com/jayway/jsonpath/ComplianceTest.java b/json-path/src/test/java/com/jayway/jsonpath/ComplianceTest.java index 0472721e..59a930cb 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/ComplianceTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/ComplianceTest.java @@ -115,6 +115,7 @@ public class ComplianceTest { " }\n" + " }"; + assertThat(JsonPath.>read(json, "$.menu.items[?(@ && @.id == 'ViewSVG')].id"), hasItems("ViewSVG")); //assertThat(JsonPath.>read(json, "$.menu.items[?(@ && @.id && !@.label)].id"), hasItems("?")); //low //assertThat(JsonPath.>read(json, "$.menu.items[?(@ && @.label && /SVG/.test(@.label))].id"), hasItems("?")); //low