diff --git a/json-path-assert/pom.xml b/json-path-assert/pom.xml
index 90f31315..7317e82d 100644
--- a/json-path-assert/pom.xml
+++ b/json-path-assert/pom.xml
@@ -31,11 +31,6 @@
${project.version}
-
- net.minidev
- json-smart
-
-
org.hamcrest
hamcrest-library
@@ -46,10 +41,5 @@
hamcrest-core
-
- junit
- junit
- test
-
diff --git a/json-path/pom.xml b/json-path/pom.xml
index 765ad701..84d775e1 100644
--- a/json-path/pom.xml
+++ b/json-path/pom.xml
@@ -26,8 +26,6 @@
json-path
http://code.google.com/p/json-path/
-
-
net.minidev
json-smart
@@ -41,33 +39,6 @@
jackson-mapper-asl
true
-
-
-
-
-
-
-
-
- org.hamcrest
- hamcrest-library
- test
-
-
-
- junit
- junit
- test
-
-
-
- commons-io
- commons-io
- test
-
-
-
-
diff --git a/json-path/src/main/java/com/jayway/jsonpath/Criteria.java b/json-path/src/main/java/com/jayway/jsonpath/Criteria.java
index 84aa642f..2d35f620 100644
--- a/json-path/src/main/java/com/jayway/jsonpath/Criteria.java
+++ b/json-path/src/main/java/com/jayway/jsonpath/Criteria.java
@@ -14,11 +14,13 @@
*/
package com.jayway.jsonpath;
+import com.jayway.jsonpath.spi.JsonProvider;
+import org.apache.commons.lang3.Validate;
+
import java.util.*;
import java.util.regex.Pattern;
import static java.util.Arrays.asList;
-import static org.apache.commons.lang3.Validate.notEmpty;
import static org.apache.commons.lang3.Validate.notNull;
/**
@@ -40,6 +42,7 @@ public class Criteria {
EXISTS,
TYPE,
REGEX,
+ NOT_EMPTY,
OR
}
@@ -58,14 +61,14 @@ public class Criteria {
private Criteria(String key) {
- notEmpty(key, "key can not be null or empty");
+ Validate.notEmpty(key, "key can not be null or empty");
this.criteriaChain = new ArrayList();
this.criteriaChain.add(this);
this.key = JsonPath.compile(key);
}
private Criteria(List criteriaChain, String key) {
- notEmpty(key, "key can not be null or empty");
+ Validate.notEmpty(key, "key can not be null or empty");
this.criteriaChain = criteriaChain;
this.criteriaChain.add(this);
this.key = JsonPath.compile(key);
@@ -226,6 +229,20 @@ public class Criteria {
return (act.size() == exp);
+ } else if (CriteriaType.NOT_EMPTY.equals(key)) {
+
+ if(actualVal == null){
+ return false;
+ }
+ boolean empty = false;
+ if (actualVal instanceof Collection) {
+ empty = ((List) actualVal).isEmpty();
+ } else if(actualVal instanceof String){
+ empty = ((String) actualVal).isEmpty();
+ }
+
+ return !empty;
+
} else if (CriteriaType.EXISTS.equals(key)) {
final boolean exp = (Boolean) expectedVal;
@@ -506,6 +523,17 @@ public class Criteria {
return this;
}
+ /**
+ * The notEmpty
operator checks that an array is not empty.
+ *
+ * @return
+ */
+ public Criteria notEmpty() {
+ checkFilterCanBeApplied(CriteriaType.NOT_EMPTY);
+ criteria.put(CriteriaType.NOT_EMPTY, null);
+ return this;
+ }
+
/**
* Check for existence (or lack thereof) of a field.
*
diff --git a/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java b/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java
index e69cd649..1821525b 100644
--- a/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java
+++ b/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java
@@ -16,6 +16,7 @@ package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.IOUtils;
+import com.jayway.jsonpath.internal.Log;
import com.jayway.jsonpath.internal.PathToken;
import com.jayway.jsonpath.internal.PathTokenizer;
import com.jayway.jsonpath.internal.filter.PathTokenFilter;
@@ -98,37 +99,44 @@ import static org.apache.commons.lang3.Validate.*;
*/
public class JsonPath {
- private static Pattern DEFINITE_PATH_PATTERN = Pattern.compile(".*(\\.\\.|\\*|\\[[\\\\/]|\\?|,|:\\s?\\]|\\[\\s?:|>|\\(|<|=|\\+).*");
+ private static Pattern DEFINITE_PATH_PATTERN = Pattern.compile(".*(\\.\\.|\\*|\\[[\\\\/]|\\?|,|:\\s?]|\\[\\s?:|>|\\(|<|=|\\+).*");
+ private static Pattern INVALID_PATH_PATTERN = Pattern.compile("[^\\?\\+=\\-\\*/!]\\(");
+
private PathTokenizer tokenizer;
private LinkedList filters;
- public JsonPath(String jsonPath, Filter[] filters) {
- if (jsonPath == null ||
- jsonPath.trim().length() == 0 ||
- jsonPath.matches("[^\\?\\+\\=\\-\\*\\/\\!]\\(")) {
+ private JsonPath(String jsonPath, Filter[] filters) {
+
+ notNull(jsonPath, "path can not be null");
+ jsonPath = jsonPath.trim();
+ notEmpty(jsonPath, "path can not be empty");
+ if (INVALID_PATH_PATTERN.matcher(jsonPath).matches()) {
throw new InvalidPathException("Invalid path");
}
+
int filterCountInPath = StringUtils.countMatches(jsonPath, "[?]");
isTrue(filterCountInPath == filters.length, "Filters in path ([?]) does not match provided filters.");
this.tokenizer = new PathTokenizer(jsonPath);
- //System.out.println(tokenizer.toString());
+ if(Log.isDebugEnabled()){
+ Log.debug("New JsonPath:\n{}", this.tokenizer.toString());
+ }
this.filters = new LinkedList();
this.filters.addAll(asList(filters));
}
- PathTokenizer getTokenizer(){
+ PathTokenizer getTokenizer() {
return this.tokenizer;
}
- public JsonPath copy(){
+ public JsonPath copy() {
return new JsonPath(tokenizer.getPath(), filters.toArray(new Filter[0]));
}
@@ -199,7 +207,7 @@ public class JsonPath {
* the {@link JsonProvider}
*
* @param jsonObject a container Object
- * @param expected return type
+ * @param expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
@@ -213,8 +221,8 @@ public class JsonPath {
* the {@link JsonProvider}
*
* @param jsonProvider JsonProvider to use
- * @param jsonObject a container Object
- * @param expected return type
+ * @param jsonObject a container Object
+ * @param expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
@@ -222,9 +230,9 @@ public class JsonPath {
notNull(jsonProvider, "jsonProvider can not be null");
notNull(jsonObject, "json can not be null");
- if(this.getPath().equals("$")){
+ if (this.getPath().equals("$")) {
//This path only references the whole object. No need to do any work here...
- return (T)jsonObject;
+ return (T) jsonObject;
}
if (!jsonProvider.isContainer(jsonObject)) {
@@ -265,8 +273,8 @@ public class JsonPath {
* Applies this JsonPath to the provided json string
*
* @param jsonProvider JsonProvider to use
- * @param json a json string
- * @param expected return type
+ * @param json a json string
+ * @param expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
@@ -294,8 +302,8 @@ public class JsonPath {
* Applies this JsonPath to the provided json URL
*
* @param jsonProvider JsonProvider to use
- * @param jsonURL url to read from
- * @param expected return type
+ * @param jsonURL url to read from
+ * @param expected return type
* @return list of objects matched by the given path
* @throws IOException
*/
@@ -331,8 +339,8 @@ public class JsonPath {
* Applies this JsonPath to the provided json file
*
* @param jsonProvider JsonProvider to use
- * @param jsonFile file to read from
- * @param expected return type
+ * @param jsonFile file to read from
+ * @param expected return type
* @return list of objects matched by the given path
* @throws IOException
*/
@@ -373,7 +381,7 @@ public class JsonPath {
/**
* Applies this JsonPath to the provided json input stream
*
- * @param jsonProvider JsonProvider to use
+ * @param jsonProvider JsonProvider to use
* @param jsonInputStream input stream to read from
* @param expected return type
* @return list of objects matched by the given path
@@ -401,7 +409,7 @@ public class JsonPath {
* Compiles a JsonPath
*
* @param jsonPath to compile
- * @param filters filters to be applied to the filter place holders [?] in the path
+ * @param filters filters to be applied to the filter place holders [?] in the path
* @return compiled JsonPath
*/
public static JsonPath compile(String jsonPath, Filter... filters) {
@@ -422,7 +430,7 @@ public class JsonPath {
*
* @param json a json string
* @param jsonPath the json path
- * @param filters filters to be applied to the filter place holders [?] in the path
+ * @param filters filters to be applied to the filter place holders [?] in the path
* @param expected return type
* @return list of objects matched by the given path
*/
@@ -436,10 +444,10 @@ public class JsonPath {
* Creates a new JsonPath and applies it to the provided Json string
*
* @param jsonProvider JsonProvider to use
- * @param json a json string
- * @param jsonPath the json path
- * @param filters filters to be applied to the filter place holders [?] in the path
- * @param expected return type
+ * @param json a json string
+ * @param jsonPath the json path
+ * @param filters filters to be applied to the filter place holders [?] in the path
+ * @param expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
@@ -456,7 +464,7 @@ public class JsonPath {
*
* @param json a json object
* @param jsonPath the json path
- * @param filters filters to be applied to the filter place holders [?] in the path
+ * @param filters filters to be applied to the filter place holders [?] in the path
* @param expected return type
* @return list of objects matched by the given path
*/
@@ -464,14 +472,15 @@ public class JsonPath {
public static T read(Object json, String jsonPath, Filter... filters) {
return read(JsonProviderFactory.createProvider(), json, jsonPath, filters);
}
+
/**
* Creates a new JsonPath and applies it to the provided Json object
*
* @param jsonProvider JsonProvider to use
- * @param json a json object
- * @param jsonPath the json path
- * @param filters filters to be applied to the filter place holders [?] in the path
- * @param expected return type
+ * @param json a json object
+ * @param jsonPath the json path
+ * @param filters filters to be applied to the filter place holders [?] in the path
+ * @param expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
@@ -489,7 +498,7 @@ public class JsonPath {
*
* @param jsonURL url pointing to json doc
* @param jsonPath the json path
- * @param filters filters to be applied to the filter place holders [?] in the path
+ * @param filters filters to be applied to the filter place holders [?] in the path
* @param expected return type
* @return list of objects matched by the given path
*/
@@ -502,10 +511,10 @@ public class JsonPath {
* Creates a new JsonPath and applies it to the provided Json object
*
* @param jsonProvider JsonProvider to use
- * @param jsonURL url pointing to json doc
- * @param jsonPath the json path
- * @param filters filters to be applied to the filter place holders [?] in the path
- * @param expected return type
+ * @param jsonURL url pointing to json doc
+ * @param jsonPath the json path
+ * @param filters filters to be applied to the filter place holders [?] in the path
+ * @param expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
@@ -520,9 +529,9 @@ public class JsonPath {
/**
* Creates a new JsonPath and applies it to the provided Json object
*
- * @param jsonFile json file
+ * @param jsonFile json file
* @param jsonPath the json path
- * @param filters filters to be applied to the filter place holders [?] in the path
+ * @param filters filters to be applied to the filter place holders [?] in the path
* @param expected return type
* @return list of objects matched by the given path
*/
@@ -535,10 +544,10 @@ public class JsonPath {
* Creates a new JsonPath and applies it to the provided Json object
*
* @param jsonProvider JsonProvider to use
- * @param jsonFile json file
- * @param jsonPath the json path
- * @param filters filters to be applied to the filter place holders [?] in the path
- * @param expected return type
+ * @param jsonFile json file
+ * @param jsonPath the json path
+ * @param filters filters to be applied to the filter place holders [?] in the path
+ * @param expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
@@ -553,10 +562,10 @@ public class JsonPath {
/**
* Creates a new JsonPath and applies it to the provided Json object
*
- * @param jsonInputStream json input stream
- * @param jsonPath the json path
- * @param filters filters to be applied to the filter place holders [?] in the path
- * @param expected return type
+ * @param jsonInputStream json input stream
+ * @param jsonPath the json path
+ * @param filters filters to be applied to the filter place holders [?] in the path
+ * @param expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
@@ -567,11 +576,11 @@ public class JsonPath {
/**
* Creates a new JsonPath and applies it to the provided Json object
*
- * @param jsonProvider JsonProvider to use
- * @param jsonInputStream json input stream
- * @param jsonPath the json path
- * @param filters filters to be applied to the filter place holders [?] in the path
- * @param expected return type
+ * @param jsonProvider JsonProvider to use
+ * @param jsonInputStream json input stream
+ * @param jsonPath the json path
+ * @param filters filters to be applied to the filter place holders [?] in the path
+ * @param expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/Log.java b/json-path/src/main/java/com/jayway/jsonpath/internal/Log.java
new file mode 100644
index 00000000..a37e68d9
--- /dev/null
+++ b/json-path/src/main/java/com/jayway/jsonpath/internal/Log.java
@@ -0,0 +1,50 @@
+package com.jayway.jsonpath.internal;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * User: kalle
+ * Date: 8/28/13
+ * Time: 10:23 AM
+ */
+public final class Log {
+
+ private Log() {
+ }
+
+ private static boolean enabled = true;
+
+ public static void enableDebug(){
+ enabled = true;
+ }
+
+ public static boolean isDebugEnabled(){
+ return enabled;
+ }
+
+ public static void debug(String msg, Object... args){
+ if(enabled){
+
+ int argCount = StringUtils.countMatches(msg, "{}");
+
+ if(!(argCount == args.length)){
+ throw new RuntimeException("Invalid debug statement.");
+ }
+
+ StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
+
+ String cls = stackTraceElements[2].getClassName();
+
+ msg = msg.replaceFirst(Pattern.quote("{}"), "%s");
+
+ msg = String.format(msg, args);
+
+ System.out.println("DEBUG [" + Thread.currentThread().getName() + "] " + cls + " " + msg);
+ }
+
+ }
+
+}
diff --git a/json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java b/json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java
index fc101ad8..c79eb69b 100644
--- a/json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java
+++ b/json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java
@@ -198,10 +198,7 @@ public class ExpressionEvalTest {
result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring)]");
assertEquals(4, result.size());
-
-
-
-
}
+
}
diff --git a/json-path/src/test/java/com/jayway/jsonpath/FilterTest.java b/json-path/src/test/java/com/jayway/jsonpath/FilterTest.java
index 2ee3a0e2..6495bc9c 100644
--- a/json-path/src/test/java/com/jayway/jsonpath/FilterTest.java
+++ b/json-path/src/test/java/com/jayway/jsonpath/FilterTest.java
@@ -1,7 +1,5 @@
package com.jayway.jsonpath;
-import net.minidev.json.parser.JSONParser;
-
import org.junit.Test;
import java.util.Collections;
@@ -258,7 +256,7 @@ public class FilterTest {
check.put("int", 10);
check.put("long", 1L);
check.put("double", 1.12D);
-
+
Filter shouldMarch = filter(where("string").is("foo").and("int").lt(11));
Filter shouldNotMarch = filter(where("string").is("foo").and("int").gt(11));
@@ -318,107 +316,141 @@ public class FilterTest {
@Test
- public void arrays_of_maps_can_be_filtered() throws Exception {
+ public void arrays_of_maps_can_be_filtered() throws Exception {
- Map rootGrandChild_A = new HashMap();
- rootGrandChild_A.put("name", "rootGrandChild_A");
+ Map rootGrandChild_A = new HashMap();
+ rootGrandChild_A.put("name", "rootGrandChild_A");
- Map rootGrandChild_B = new HashMap();
- rootGrandChild_B.put("name", "rootGrandChild_B");
+ Map rootGrandChild_B = new HashMap();
+ rootGrandChild_B.put("name", "rootGrandChild_B");
- Map rootGrandChild_C = new HashMap();
- rootGrandChild_C.put("name", "rootGrandChild_C");
+ Map rootGrandChild_C = new HashMap();
+ rootGrandChild_C.put("name", "rootGrandChild_C");
- Map rootChild_A = new HashMap();
- rootChild_A.put("name", "rootChild_A");
- rootChild_A.put("children", asList(rootGrandChild_A, rootGrandChild_B, rootGrandChild_C));
+ Map rootChild_A = new HashMap();
+ rootChild_A.put("name", "rootChild_A");
+ rootChild_A.put("children", asList(rootGrandChild_A, rootGrandChild_B, rootGrandChild_C));
- Map rootChild_B = new HashMap();
- rootChild_B.put("name", "rootChild_B");
- rootChild_B.put("children", asList(rootGrandChild_A, rootGrandChild_B, rootGrandChild_C));
+ Map rootChild_B = new HashMap();
+ rootChild_B.put("name", "rootChild_B");
+ rootChild_B.put("children", asList(rootGrandChild_A, rootGrandChild_B, rootGrandChild_C));
- Map rootChild_C = new HashMap();
- rootChild_C.put("name", "rootChild_C");
- rootChild_C.put("children", asList(rootGrandChild_A, rootGrandChild_B, rootGrandChild_C));
+ Map rootChild_C = new HashMap();
+ rootChild_C.put("name", "rootChild_C");
+ rootChild_C.put("children", asList(rootGrandChild_A, rootGrandChild_B, rootGrandChild_C));
- Map root = new HashMap();
- root.put("children", asList(rootChild_A, rootChild_B, rootChild_C));
+ Map root = new HashMap();
+ root.put("children", asList(rootChild_A, rootChild_B, rootChild_C));
-
- Filter customFilter = new Filter.FilterAdapter