From f3e682f5878413e36e4ac565039eec4dc9bd0960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Charri=C3=A8re?= Date: Thu, 13 Feb 2014 12:19:49 +0100 Subject: [PATCH] ArrayEvalFilter: add support for Javascript-style regular expressions. --- .../internal/filter/ArrayEvalFilter.java | 37 +++++++++++++++++++ .../com/jayway/jsonpath/ComplianceTest.java | 12 +++--- 2 files changed, 43 insertions(+), 6 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 416e9aea..1473eba8 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 @@ -33,6 +33,7 @@ public class ArrayEvalFilter extends PathTokenFilter { private static final Pattern CONDITION_PATTERN = Pattern.compile("\\s?(@.*?)\\s?([!=<>]+)\\s?(.*?)\\s?"); private static final Pattern FIELD_EXISTS_PATTERN = Pattern.compile("\\s?@\\s?(.*?)\\s?"); private static final Pattern HASPATH_PATTERN = Pattern.compile("\\s?(@\\..*)\\s?(.*?)\\s?"); + private static final Pattern REGEX_PATTERN = Pattern.compile("\\s?\\/(.*)\\/\\.test\\((@\\..*)\\)\\s?"); private Expression[] expressions; @@ -108,6 +109,12 @@ public class ArrayEvalFilter extends PathTokenFilter { // evaluates @ or @.foo in expressions return new HasPathExpression(condition); } + Matcher regexMatcher = REGEX_PATTERN.matcher(condition); + if (regexMatcher.matches()) { + String regex = regexMatcher.group(1).trim(); + String field = regexMatcher.group(2).trim(); + return new RegexExpression(regex, field); + } Matcher fieldExistsMatcher = FIELD_EXISTS_PATTERN.matcher(condition); if (fieldExistsMatcher.matches()) { // Field exists check, the single '@' in: $.menu.items[?(@ && @.id == 'ViewSVG')].id @@ -239,4 +246,34 @@ public class ArrayEvalFilter extends PathTokenFilter { return false; } } + + static class RegexExpression extends Expression { + private Pattern pattern; + private JsonPath path; + + public RegexExpression(String regex, String field) { + pattern = Pattern.compile(regex); + if(field.startsWith("@.")){ + this.path = JsonPath.compile(field.replace("@.", "$.")); + } else { + this.path = JsonPath.compile(field.replace("@", "$")); + } + } + + @Override + public boolean evaluate(Object obj, Configuration configuration) { + JsonProvider jsonProvider = configuration.getProvider(); + + if(jsonProvider.isMap(obj)){ + try{ + Object value = (obj != null) ? path.read(obj, configuration.options(Option.THROW_ON_MISSING_PROPERTY)) : null; + return (value instanceof String) && pattern.matcher((String)value).find(); + } catch (PathNotFoundException e){ + return false; + } + } + return false; + } + + } } 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 59a930cb..4dd22d48 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/ComplianceTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/ComplianceTest.java @@ -32,7 +32,7 @@ public class ComplianceTest { //assertThat(JsonPath.>read(json, "$[*]"), hasItems("a", "b", "e")); //low } - + @Test public void test_two() throws Exception { String json = "[ 1, \"2\", 3.14, true, null ]"; @@ -118,7 +118,7 @@ public class ComplianceTest { 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 + assertThat(JsonPath.>read(json, "$.menu.items[?(@ && @.label && /SVG/.test(@.label))].id"), hasItems("CopySVG", "ViewSVG")); //low //assertThat(JsonPath.>read(json, "$.menu.items[?(!@)]"), hasItems("?")); //low //assertThat(JsonPath.>read(json, "$..[0]"), hasItems("?")); //low @@ -145,7 +145,7 @@ public class ComplianceTest { "p": [ "$[0]", "$[4]", "$[*]", - "$[-1:]" + "$[-1:]" ] }, --three @@ -199,7 +199,7 @@ public class ComplianceTest { "p": [ "$.menu.items[?(@ && @.id && !@.label)].id", "$.menu.items[?(@ && @.label && /SVG/.test(@.label))].id", "$.menu.items[?(!@)]", - "$..[0]" + "$..[0]" ] }, --five @@ -207,8 +207,8 @@ public class ComplianceTest { b: [5,6,7,8] }, "p": [ "$..[0]", - "$..[-1:]", - "$..[?(@%2==0)]" + "$..[-1:]", + "$..[?(@%2==0)]" ] }, { "o": { lin: {color:"red", x:2, y:3},