diff --git a/changelog.txt b/changelog.txt
index e69de29b..f3d46a9f 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -0,0 +1,8 @@
+------------------------------------------
+0.5.2
+------------------------------------------
+
+- Fixed issue that path was never considered definite if containing a ':'
+- Bracket notation is now first class citizen $.foo.bar == $.['foo'].['bar']
+- Added JsonAsserter.assertNotDefined(String path) to allow checks for negative existence of a path
+
diff --git a/json-path-assert/src/main/java/com/jayway/jsonassert/JsonAsserter.java b/json-path-assert/src/main/java/com/jayway/jsonassert/JsonAsserter.java
index 0f0024ab..9cff5bec 100644
--- a/json-path-assert/src/main/java/com/jayway/jsonassert/JsonAsserter.java
+++ b/json-path-assert/src/main/java/com/jayway/jsonassert/JsonAsserter.java
@@ -16,7 +16,7 @@ public interface JsonAsserter {
*
*
* with(json).assertThat("items[0].name", equalTo("Bobby"))
- * .assertThat("items[0].age" , equalTo(24L))
+ * .assertThat("items[0].age" , equalTo(24L))
*
*
* @param path the json path specifying the value being compared
@@ -37,6 +37,16 @@ public interface JsonAsserter {
*/
JsonAsserter assertEquals(String path, T expected);
+ /**
+ * Checks that a path is not defined within a document. If the document contains the
+ * given path, an AssertionError is thrown
+ *
+ * @param path the path to make sure not exists
+ * @return this
+ */
+ JsonAsserter assertNotDefined(String path);
+
+
/**
* Asserts that object specified by path is null. If it is not, an AssertionError
* is thrown with the given message.
diff --git a/json-path-assert/src/main/java/com/jayway/jsonassert/impl/JsonAsserterImpl.java b/json-path-assert/src/main/java/com/jayway/jsonassert/impl/JsonAsserterImpl.java
index aa5073c2..fb650aaf 100644
--- a/json-path-assert/src/main/java/com/jayway/jsonassert/impl/JsonAsserterImpl.java
+++ b/json-path-assert/src/main/java/com/jayway/jsonassert/impl/JsonAsserterImpl.java
@@ -4,13 +4,10 @@ package com.jayway.jsonassert.impl;
import com.jayway.jsonassert.JsonAsserter;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.PathUtil;
-import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
-import java.text.ParseException;
-import java.util.List;
-
+import static java.lang.String.format;
import static org.hamcrest.Matchers.*;
/**
@@ -21,7 +18,6 @@ import static org.hamcrest.Matchers.*;
public class JsonAsserterImpl implements JsonAsserter {
-
private final Object jsonObject;
@@ -35,20 +31,18 @@ public class JsonAsserterImpl implements JsonAsserter {
}
-
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
- public JsonAsserter assertThat(String path, Matcher matcher) {
+ public JsonAsserter assertThat(String path, Matcher matcher) {
String reason = "When processing json path: " + path;
- if(PathUtil.isPathDefinite(path)){
+ if (PathUtil.isPathDefinite(path)) {
MatcherAssert.assertThat(reason, JsonPath.readOne(jsonObject, path), matcher);
- }
- else {
- MatcherAssert.assertThat(reason, (T) JsonPath.read(jsonObject, path), matcher);
+ } else {
+ MatcherAssert.assertThat(reason, (T) JsonPath.read(jsonObject, path), matcher);
}
return this;
}
@@ -60,6 +54,18 @@ public class JsonAsserterImpl implements JsonAsserter {
return assertThat(path, equalTo(expected));
}
+ /**
+ * {@inheritDoc}
+ */
+ public JsonAsserter assertNotDefined(String path) {
+ Object o = JsonPath.readOne(jsonObject, path);
+
+ if(o != null){
+ throw new AssertionError(format("Document contains the path <%s> but was expected not to.", path));
+ }
+ return this;
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/json-path-assert/src/test/java/com/jayway/jsonassert/JsonAssertTest.java b/json-path-assert/src/test/java/com/jayway/jsonassert/JsonAssertTest.java
index 31833e7f..513e5385 100644
--- a/json-path-assert/src/test/java/com/jayway/jsonassert/JsonAssertTest.java
+++ b/json-path-assert/src/test/java/com/jayway/jsonassert/JsonAssertTest.java
@@ -3,6 +3,8 @@ package com.jayway.jsonassert;
import org.hamcrest.Matchers;
import org.junit.Test;
+import java.io.InputStream;
+
import static com.jayway.jsonassert.JsonAssert.*;
import static org.hamcrest.Matchers.*;
@@ -41,11 +43,40 @@ public class JsonAssertTest {
" ],\n" +
" \"bicycle\": {\n" +
" \"color\": \"red\",\n" +
- " \"price\": 19.95\n" +
+ " \"price\": 19.95\n," +
+ " \"nullValue\": null\n" +
" }\n" +
" }\n" +
"}";
+
+ @Test
+ public void links_document() throws Exception {
+
+ with(getResourceAsStream("links.json")).assertEquals("count", 2L)
+ .assertThat("links.gc:this.href", endsWith("?pageNumber=1&pageSize=2"))
+ .assertNotDefined("links.gc:prev")
+ .assertNotDefined("links.gc:next")
+ .assertThat("rows", collectionWithSize(equalTo(2)));
+
+ }
+
+
+ @Test
+ public void a_document_can_be_expected_not_to_contain_a_path() throws Exception {
+ with(JSON).assertNotDefined("$.store.bicycle.cool");
+ }
+
+ @Test
+ public void a_value_can_asserted_to_be_null() throws Exception {
+ with(JSON).assertNull("$.store.bicycle.nullValue");
+ }
+
+ @Test
+ public void ends_with_evalueates() throws Exception {
+ with(JSON).assertThat("$.store.book[0].category", endsWith("nce"));
+ }
+
@Test
public void a_path_can_be_asserted_with_matcher() throws Exception {
@@ -78,6 +109,15 @@ public class JsonAssertTest {
.assertThat("$.store.book[0]", mapContainingKey(equalTo("category")))
.and()
.assertThat("$.store.book[0]", mapContainingValue(equalTo("reference")));
+
+ with(JSON).assertThat("$.['store'].['book'][0]", hasEntry("category", "reference"))
+ .assertThat("$.['store'].['book'][0]", hasEntry("title", "Sayings of the Century"))
+ .and()
+ .assertThat("$..['book'][0]", hasItems(hasEntry("category", "reference")))
+ .and()
+ .assertThat("$.['store'].['book'][0]", mapContainingKey(equalTo("category")))
+ .and()
+ .assertThat("$.['store'].['book'][0]", mapContainingValue(equalTo("reference")));
}
@Test
@@ -102,4 +142,9 @@ public class JsonAssertTest {
with(JSON).assertThat("$.store.book[*].fooBar", emptyCollection());
}
+
+ private InputStream getResourceAsStream(String resourceName) {
+ return getClass().getClassLoader().getResourceAsStream(resourceName);
+ }
+
}
diff --git a/json-path-assert/src/test/resources/links.json b/json-path-assert/src/test/resources/links.json
new file mode 100644
index 00000000..a3ecfac9
--- /dev/null
+++ b/json-path-assert/src/test/resources/links.json
@@ -0,0 +1,49 @@
+{
+ "links": {
+ "gc:this": {
+ "rel": "gc:this",
+ "href": "/rest/account/market/incentives?pageNumber=1&pageSize=2"
+ }
+ },
+ "count": 2,
+ "pageNumber": 1,
+ "pageSize": 2,
+ "rows": [{
+ "id": "cd646745-5834-4244-9126-fa631c32693c",
+ "price": 10,
+ "title": "A TITLE",
+ "description": "description",
+ "smallIcon": "small.ico",
+ "categories": ["cd646745-5834-4244-9126-fa631c32693c"],
+ "brand": {
+ "id": "8d0280ae-8ea3-4ae1-b46c-f0fc0b293066",
+ "name": "brand.name",
+ "picture": "brand.picture"
+ },
+ "links": {
+ "gc:market:incentive": {
+ "rel": "gc:market:incentive",
+ "href": "/rest/account/market/incentives/cd646745-5834-4244-9126-fa631c32693c"
+ }
+ }
+ },
+ {
+ "id": "cd646745-5834-4244-9126-fa631c32693c2",
+ "price": 10,
+ "title": "B TITLE",
+ "description": "description",
+ "smallIcon": "small.ico",
+ "categories": ["cd646745-5834-4244-9126-fa631c32693c"],
+ "brand": {
+ "id": "8d0280ae-8ea3-4ae1-b46c-f0fc0b293066",
+ "name": "brand.name",
+ "picture": "brand.picture"
+ },
+ "links": {
+ "gc:market:incentive": {
+ "rel": "gc:market:incentive",
+ "href": "/rest/account/market/incentives/cd646745-5834-4244-9126-fa631c32693c2"
+ }
+ }
+ }]
+}
diff --git a/json-path/src/main/java/com/jayway/jsonpath/PathUtil.java b/json-path/src/main/java/com/jayway/jsonpath/PathUtil.java
index a43056ac..fb868c4b 100644
--- a/json-path/src/main/java/com/jayway/jsonpath/PathUtil.java
+++ b/json-path/src/main/java/com/jayway/jsonpath/PathUtil.java
@@ -32,7 +32,8 @@ public class PathUtil {
* @return true if path is definite (points to single item)
*/
public static boolean isPathDefinite(String jsonPath) {
- return !jsonPath.replaceAll("\"[^\"\\\\\\n\r]*\"", "").matches(".*(\\.\\.|\\*|\\[[\\\\/]|\\?|,|:|>|\\(|<|=|\\+).*");
+ //return !jsonPath.replaceAll("\"[^\"\\\\\\n\r]*\"", "").matches(".*(\\.\\.|\\*|\\[[\\\\/]|\\?|,|:|>|\\(|<|=|\\+).*");
+ return !jsonPath.replaceAll("\"[^\"\\\\\\n\r]*\"", "").matches(".*(\\.\\.|\\*|\\[[\\\\/]|\\?|,|:\\s?\\]|\\[\\s?:|>|\\(|<|=|\\+).*");
}
/**
diff --git a/json-path/src/main/java/com/jayway/jsonpath/filter/JsonPathFilterFactory.java b/json-path/src/main/java/com/jayway/jsonpath/filter/JsonPathFilterFactory.java
index 3ed84afe..97ffe254 100644
--- a/json-path/src/main/java/com/jayway/jsonpath/filter/JsonPathFilterFactory.java
+++ b/json-path/src/main/java/com/jayway/jsonpath/filter/JsonPathFilterFactory.java
@@ -10,8 +10,8 @@ import java.util.regex.Pattern;
public class JsonPathFilterFactory {
private final static Pattern ROOT_FILTER_PATTERN = Pattern.compile("\\$");
- private final static Pattern PROPERTY_FILTER_PATTERN = Pattern.compile("(\\w+)|\\['(\\w+)'\\]");
- //private final static Pattern PROPERTY_FILTER_PATTERN = Pattern.compile("\\w+");
+ //private final static Pattern PROPERTY_FILTER_PATTERN = Pattern.compile("(\\w+)|\\['(\\w+)'\\]");
+ private final static Pattern PROPERTY_FILTER_PATTERN = Pattern.compile("(.*)|\\['(.*?)'\\]");
private final static Pattern WILDCARD_PROPERTY_FILTER_PATTERN = Pattern.compile("\\*");
private final static Pattern LIST_FILTER_PATTERN = Pattern.compile("\\[.*?\\]");
private final static Pattern TRAVERSE_FILTER_PATTERN = Pattern.compile("\\.\\.");
@@ -26,15 +26,15 @@ public class JsonPathFilterFactory {
if(ROOT_FILTER_PATTERN.matcher(pathFragment).matches()){
return ROOT_FILTER;
}
- else if(PROPERTY_FILTER_PATTERN.matcher(pathFragment).matches() || WILDCARD_PROPERTY_FILTER_PATTERN.matcher(pathFragment).matches() ){
- return new PropertyFilter(pathFragment);
- }
else if(LIST_FILTER_PATTERN.matcher(pathFragment).matches()){
return new ListFilter(pathFragment);
}
else if(TRAVERSE_FILTER_PATTERN.matcher(pathFragment).matches()){
return TRAVERSE_FILTER;
}
+ else if(PROPERTY_FILTER_PATTERN.matcher(pathFragment).matches() || WILDCARD_PROPERTY_FILTER_PATTERN.matcher(pathFragment).matches() ){
+ return new PropertyFilter(pathFragment);
+ }
return null;
}
diff --git a/json-path/src/test/java/com/jayway/jsonpath/JsonPathTest.java b/json-path/src/test/java/com/jayway/jsonpath/JsonPathTest.java
index 7c17be50..86be95a3 100644
--- a/json-path/src/test/java/com/jayway/jsonpath/JsonPathTest.java
+++ b/json-path/src/test/java/com/jayway/jsonpath/JsonPathTest.java
@@ -1,6 +1,5 @@
package com.jayway.jsonpath;
-import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import java.util.List;
@@ -46,11 +45,19 @@ public class JsonPathTest {
" ],\n" +
" \"bicycle\": {\n" +
" \"color\": \"red\",\n" +
- " \"price\": 19.95\n" +
+ " \"price\": 19.95,\n" +
+ " \"foo:bar\": \"fooBar\"\n" +
" }\n" +
" }\n" +
"}";
+ @Test
+ public void read_path_with_colon() throws Exception {
+
+ assertEquals(JsonPath.readOne(DOCUMENT, "$.store.bicycle.foo:bar"), "fooBar");
+ assertEquals(JsonPath.readOne(DOCUMENT, "$.['store'].['bicycle'].['foo:bar']"), "fooBar");
+ }
+
@Test
public void read_document_from_root() throws Exception {
@@ -165,11 +172,12 @@ public class JsonPathTest {
assertTrue(res.isEmpty());
}
-
+ /*
@Test(expected = InvalidPathException.class)
public void invalid_space_path_throws_exception() throws Exception {
JsonPath.read(DOCUMENT, "space is not good");
}
+ */
@Test(expected = InvalidPathException.class)
public void invalid_new_path_throws_exception() throws Exception {
diff --git a/json-path/src/test/java/com/jayway/jsonpath/PathUtilTest.java b/json-path/src/test/java/com/jayway/jsonpath/PathUtilTest.java
index a609e8d4..0f183f50 100644
--- a/json-path/src/test/java/com/jayway/jsonpath/PathUtilTest.java
+++ b/json-path/src/test/java/com/jayway/jsonpath/PathUtilTest.java
@@ -3,6 +3,7 @@ package com.jayway.jsonpath;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
/**
* Created by IntelliJ IDEA.
@@ -18,5 +19,12 @@ public class PathUtilTest {
assertFalse(PathUtil.isPathDefinite("$..book[0]"));
}
+ @Test
+ public void is_definite() throws Exception {
+ assertTrue(PathUtil.isPathDefinite("$.definite.this.is"));
+ assertTrue(PathUtil.isPathDefinite("$.definite:this.is"));
+ assertTrue(PathUtil.isPathDefinite("rows[0].id"));
+ }
+
}
diff --git a/json-path/src/test/java/com/jayway/jsonpath/SplitPathFragmentsTest.java b/json-path/src/test/java/com/jayway/jsonpath/SplitPathFragmentsTest.java
index e0270ba4..a5650bee 100644
--- a/json-path/src/test/java/com/jayway/jsonpath/SplitPathFragmentsTest.java
+++ b/json-path/src/test/java/com/jayway/jsonpath/SplitPathFragmentsTest.java
@@ -60,6 +60,8 @@ public class SplitPathFragmentsTest {
assertThat(PathUtil.splitPath("$.[0][1].author"), hasItems("$", "[0]", "[1]", "author"));
assertThat(PathUtil.splitPath("$.[0].[1].author"), hasItems("$", "[0]", "[1]", "author"));
+
+ assertThat(PathUtil.splitPath("$.foo:bar.author"), hasItems("$", "foo:bar", "author"));
}