[go: nahoru, domu]

Skip to content

Commit

Permalink
Support for regex in inline filters.
Browse files Browse the repository at this point in the history
  • Loading branch information
kallestenflo committed Oct 26, 2014
1 parent de80e5c commit 78c8d90
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 5 deletions.
6 changes: 6 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ In The Pipe
`parse(JSON_DOCUMENT).put("$.store.book[1]", "new-key", "new-val")`
`parse(JSON_DOCUMENT).add("$.store.book", newBook)`
`parse(JSON_DOCUMENT).delete("$.store.book[1].display-price")`
* Support regex in inline filters (ruby syntax)
`parse(JSON_DOCUMENT).read("$.store.book[?(@.category =~ /reference/)].author")`
`parse(JSON_DOCUMENT).read("$.store.book[?(@.category =~ /REFERENCE/i)].author")`
* Inline filter does not force path first
`parse(JSON_DOCUMENT).read("$.store.book[?(@.category == 'reference')].author")`
`parse(JSON_DOCUMENT).read("$.store.book[?('reference' == @.category)].author")`


1.1.0 (2014-10-01)
Expand Down
49 changes: 44 additions & 5 deletions json-path/src/main/java/com/jayway/jsonpath/Criteria.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ public class Criteria implements Predicate {
CriteriaType.LTE.toString(),
CriteriaType.NE.toString(),
CriteriaType.LT.toString(),
CriteriaType.GT.toString()
CriteriaType.GT.toString(),
CriteriaType.REGEX.toString()
};

private Object left;
Expand Down Expand Up @@ -232,13 +233,27 @@ boolean eval(Object left, Object right, PredicateContext ctx) {
@Override
boolean eval(Object left, Object right, PredicateContext ctx) {
boolean res = false;
final Pattern pattern = (Pattern) left;
if (right != null && right instanceof String) {
res = pattern.matcher(right.toString()).matches();
Pattern pattern;
Object target;

if(right instanceof Pattern){
pattern = (Pattern) right;
target = left;
} else {
pattern = (Pattern) left;
target = right;
}

if(target != null){
res = pattern.matcher(target.toString()).matches();
}
if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", right, name(), left.toString(), res);
if(logger.isDebugEnabled()) logger.debug("[{}] {} [{}] => {}", right.toString(), name(), left.toString(), res);
return res;
}
@Override
public String toString() {
return "=~";
}
},
MATCHES {
@Override
Expand Down Expand Up @@ -282,6 +297,8 @@ public static CriteriaType parse(String str) {
return LTE;
} else if ("!=".equals(str)) {
return NE;
} else if ("=~".equals(str)) {
return REGEX;
} else {
throw new UnsupportedOperationException("CriteriaType " + str + " can not be parsed");
}
Expand Down Expand Up @@ -639,9 +656,27 @@ public Criteria matches(Predicate p) {
private static boolean isPath(String string){
return (string != null && (string.startsWith("$") || string.startsWith("@")));
}

private static boolean isString(String string){
return (string != null && !string.isEmpty() && string.charAt(0) == '\'' && string.charAt(string.length() - 1) == '\'');
}
private static boolean isPattern(String string){
return (string != null
&& !string.isEmpty()
&& string.charAt(0) == '/'
&& (string.charAt(string.length() - 1) == '/' || (string.charAt(string.length() - 2) == '/' && string.charAt(string.length() - 1) == 'i'))
);
}

private static Pattern compilePattern(String string) {
int lastIndex = string.lastIndexOf('/');
boolean ignoreCase = string.endsWith("i");
String regex = string.substring(1, lastIndex);

int flags = ignoreCase ? Pattern.CASE_INSENSITIVE : 0;
return Pattern.compile(regex, flags);
}



/**
Expand Down Expand Up @@ -691,6 +726,8 @@ public static Criteria create(String left, String operator, String right) {
leftPrepared = leftPath;
} else if(isString(left)) {
leftPrepared = left.substring(1, left.length() - 1);
} else if(isPattern(left)){
leftPrepared = compilePattern(left);
}

if(isPath(right)){
Expand All @@ -701,6 +738,8 @@ public static Criteria create(String left, String operator, String right) {
rightPrepared = rightPath;
} else if(isString(right)) {
rightPrepared = right.substring(1, right.length() - 1);
} else if(isPattern(right)){
rightPrepared = compilePattern(right);
}

if(leftPath != null && operator.isEmpty()){
Expand Down
20 changes: 20 additions & 0 deletions json-path/src/test/java/com/jayway/jsonpath/InlineFilterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,24 @@ public void path_can_be_on_both_side_of_operator() {

assertThat(res).containsExactly("Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien");
}

@Test
public void patterns_can_be_evaluated() {
List<String> resLeft = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?(@.category =~ /reference/)].author");
assertThat(resLeft).containsExactly("Nigel Rees");

resLeft = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?(/reference/ =~ @.category)].author");
assertThat(resLeft).containsExactly("Nigel Rees");
}



@Test
public void patterns_can_be_evaluated_with_ignore_case() {
List<String> resLeft = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?(@.category =~ /REFERENCE/)].author");
assertThat(resLeft).isEmpty();

resLeft = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?(@.category =~ /REFERENCE/i)].author");
assertThat(resLeft).containsExactly("Nigel Rees");
}
}

0 comments on commit 78c8d90

Please sign in to comment.