Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.jayway.jsonpath.JsonPathException;
import com.jayway.jsonpath.Predicate;
import com.jayway.jsonpath.internal.path.PredicateContextImpl;

import java.util.HashMap;
import java.util.Iterator;
Expand Down Expand Up @@ -253,23 +254,51 @@ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateCont
private static class RegexpEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
if(!(left.isPatternNode() ^ right.isPatternNode())){
return false;
}

if (left.isPatternNode()) {
if (right.isValueListNode() || (right.isJsonNode() && right.asJsonNode().isArray(ctx))) {
return matchesAny(left.asPatternNode(), right.asJsonNode().asValueListNode(ctx));
if(left.isPatternNode() ^ right.isPatternNode()){
if (left.isPatternNode()) {
if (right.isValueListNode() || (right.isJsonNode() && right.asJsonNode().isArray(ctx))) {
return matchesAny(left.asPatternNode(), right.asJsonNode().asValueListNode(ctx));
} else {
return matches(left.asPatternNode(), getInput(right));
}
} else {
return matches(left.asPatternNode(), getInput(right));
if (left.isValueListNode() || (left.isJsonNode() && left.asJsonNode().isArray(ctx))) {
return matchesAny(right.asPatternNode(), left.asJsonNode().asValueListNode(ctx));
} else {
return matches(right.asPatternNode(), getInput(left));
}
}
} else {
if (left.isValueListNode() || (left.isJsonNode() && left.asJsonNode().isArray(ctx))) {
return matchesAny(right.asPatternNode(), left.asJsonNode().asValueListNode(ctx));
} else {
return matches(right.asPatternNode(), getInput(left));
}

if(!left.isPatternNode() && !right.isPatternNode()){
String leftStr = getInput(left);
String rightStr = getInput(right);

if (!leftStr.isEmpty() && !rightStr.isEmpty()) {
try {
Pattern pattern;

if (ctx instanceof PredicateContextImpl) {
PredicateContextImpl ctxi = (PredicateContextImpl) ctx;
HashMap<String, Pattern> cache = ctxi.compiledPatternCache();

pattern = cache.get(rightStr);
if (pattern == null) {
pattern = Pattern.compile(rightStr);
cache.put(rightStr, pattern);
}
} else {
pattern = Pattern.compile(rightStr);
}

return pattern.matcher(leftStr).matches();
} catch (Exception e) {
return false;
}
}
}

return false;
}

private boolean matches(PatternNode patternNode, String inputToMatch) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.regex.Pattern;

public class PredicateContextImpl implements Predicate.PredicateContext {

Expand All @@ -32,11 +33,14 @@ public class PredicateContextImpl implements Predicate.PredicateContext {
private final Configuration configuration;
private final HashMap<Path, Object> documentPathCache;

private final HashMap<String, Pattern> compiledPatternCache;

public PredicateContextImpl(Object contextDocument, Object rootDocument, Configuration configuration, HashMap<Path, Object> documentPathCache) {
this.contextDocument = contextDocument;
this.rootDocument = rootDocument;
this.configuration = configuration;
this.documentPathCache = documentPathCache;
this.compiledPatternCache = new HashMap<String, Pattern>();
}

public Object evaluate(Path path){
Expand All @@ -59,6 +63,10 @@ public HashMap<Path, Object> documentPathCache() {
return documentPathCache;
}

public HashMap<String, Pattern> compiledPatternCache() {
return compiledPatternCache;
}

@Override
public Object item() {
return contextDocument;
Expand Down
41 changes: 41 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 @@ -175,6 +175,47 @@ public void patterns_match_against_lists() {
assertThat(haveRefBooks).containsExactly("First");
}

@Test
public void dynamic_patterns_can_be_evaluated() {
String json = "{\n" +
" \"pattern\": \"business\",\n" +
" \"tags\": [\"business\", \"info\"]\n" +
"}";

List<String> result = JsonPath.parse(json).read("$.tags[?(@ =~ $.pattern)]");
assertThat(result).containsExactly("business");
}

@Test
public void dynamic_patterns_use_cache_during_evaluation() {
String json = "{\n" +
" \"pattern\": \"test.*\",\n" +
" \"items\": [\"test1\", \"test2\", \"other\", \"test3\"]\n" +
"}";

List<String> result = JsonPath.parse(json).read("$.items[?(@ =~ $.pattern)]");
assertThat(result).containsExactly("test1", "test2", "test3");
}

@Test
public void dynamic_patterns_do_not_share_cache_between_executions() {
String json1 = "{\n" +
" \"pattern\": \"foo\",\n" +
" \"items\": [\"foo\", \"bar\"]\n" +
"}";

String json2 = "{\n" +
" \"pattern\": \"bar\",\n" +
" \"items\": [\"foo\", \"bar\"]\n" +
"}";

List<String> result1 = JsonPath.parse(json1).read("$.items[?(@ =~ $.pattern)]");
assertThat(result1).containsExactly("foo");

List<String> result2 = JsonPath.parse(json2).read("$.items[?(@ =~ $.pattern)]");
assertThat(result2).containsExactly("bar");
}

@Test
public void negate_exists_check() {
List<String> hasIsbn = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[?(@.isbn)].author");
Expand Down