Browse Source

improved path error messages

pull/1/merge
kalle 14 years ago
parent
commit
bd586d5b11
  1. 15
      json-assert/src/main/java/com/jayway/jsonassert/InvalidPathException.java
  2. 23
      json-assert/src/main/java/com/jayway/jsonassert/impl/JSONPathFragment.java
  3. 36
      json-assert/src/main/java/com/jayway/jsonassert/impl/JSONReaderImpl.java
  4. 3
      json-assert/src/test/java/com/jayway/jsonassert/JSONReaderTest.java
  5. 42
      json-assert/src/test/resources/json-test-doc.json

15
json-assert/src/main/java/com/jayway/jsonassert/InvalidPathException.java

@ -6,4 +6,19 @@ package com.jayway.jsonassert;
* Time: 10:09 AM * Time: 10:09 AM
*/ */
public class InvalidPathException extends RuntimeException { public class InvalidPathException extends RuntimeException {
public InvalidPathException() {
}
public InvalidPathException(String message) {
super(message);
}
public InvalidPathException(String message, Throwable cause) {
super(message, cause);
}
public InvalidPathException(Throwable cause) {
super(cause);
}
} }

23
json-assert/src/main/java/com/jayway/jsonassert/impl/JSONPathFragment.java

@ -22,10 +22,31 @@ class JSONPathFragment {
this.fragment = fragment; this.fragment = fragment;
} }
String fragment() { String value() {
return fragment; return fragment;
} }
String appendToPath(String path){
StringBuilder builder = new StringBuilder(path);
if(ARRAY_POSITION_PATTER.matcher(fragment).matches()){
builder.append("[").append(getArrayIndex()).append("]");
}
else if(GROOVY_POSITION_PATTER.matcher(fragment).matches()){
builder.append(path.isEmpty()?"":".").append("get(").append(getArrayIndex()).append(")");
}
else if(ARRAY_WILDCARD_PATTER.matcher(fragment).matches()){
builder.append("[*]");
}
else if(GROOVY_WILDCARD_PATTER.matcher(fragment).matches()){
builder.append(path.isEmpty()?"":".").append("get(*)");
}
else {
builder.append(path.isEmpty()?"":".").append(fragment);
}
return builder.toString();
}
boolean isArrayIndex() { boolean isArrayIndex() {
return ARRAY_POSITION_PATTER.matcher(fragment).matches() || GROOVY_POSITION_PATTER.matcher(fragment).matches(); return ARRAY_POSITION_PATTER.matcher(fragment).matches() || GROOVY_POSITION_PATTER.matcher(fragment).matches();
} }

36
json-assert/src/main/java/com/jayway/jsonassert/impl/JSONReaderImpl.java

@ -26,6 +26,7 @@ public class JSONReaderImpl implements JSONReader {
private static final JSONParser JSON_PARSER = new JSONParser(); private static final JSONParser JSON_PARSER = new JSONParser();
private Object root; private Object root;
private String currentPath;
public static synchronized JSONReader parse(Reader reader) throws java.text.ParseException, IOException { public static synchronized JSONReader parse(Reader reader) throws java.text.ParseException, IOException {
@ -130,27 +131,32 @@ public class JSONReaderImpl implements JSONReader {
private <T> T getByPath(Class<T> clazz, String stringPath) { private <T> T getByPath(Class<T> clazz, String stringPath) {
currentPath = "";
Object current = this.root; Object current = this.root;
JSONPath path = new JSONPath(stringPath); JSONPath path = new JSONPath(stringPath);
while (path.hasMoreFragments()) { while (path.hasMoreFragments()) {
JSONPathFragment fragment = path.nextFragment(); JSONPathFragment fragment = path.nextFragment();
currentPath = fragment.appendToPath(currentPath);
if (fragment.isArrayIndex()) { if (fragment.isArrayIndex()) {
current = getArray(current).get(fragment.getArrayIndex()); current = toArray(current).get(fragment.getArrayIndex());
} else if (fragment.isArrayWildcard()) { } else if (fragment.isArrayWildcard()) {
current = getContainerValue(current, path.nextFragment().fragment()); current = getContainerValue(current, path.nextFragment());
} else { } else {
current = getContainerValue(current, fragment.fragment()); current = getContainerValue(current, fragment);
} }
} }
return clazz.cast(current); return clazz.cast(current);
} }
private JSONArray getArray(Object array) { private JSONArray toArray(Object array) {
return (JSONArray) array; return (JSONArray) array;
} }
private JSONObject getDocument(Object document) { private JSONObject toDocument(Object document) {
return (JSONObject) document; return (JSONObject) document;
} }
@ -161,32 +167,30 @@ public class JSONReaderImpl implements JSONReader {
* will be returned in a List * will be returned in a List
* *
* @param container a json document or array * @param container a json document or array
* @param field the field to extract from the document alt. the documents contained in the array * @param fragment the field to extract from the document alt. the documents contained in the array
* @return a single field value or a List of fields * @return a single field value or a List of fields
*/ */
private Object getContainerValue(Object container, Object field) { private Object getContainerValue(Object container, JSONPathFragment fragment) {
Object result; Object result;
if (container instanceof JSONArray) { if (container instanceof JSONArray) {
List list = new LinkedList(); List list = new LinkedList();
for (Object doc : getArray(container)) { for (Object doc : toArray(container)) {
list.add(getContainerValue(doc, field)); list.add(getContainerValue(doc, fragment));
} }
result = list; result = list;
} else if (container instanceof JSONObject) { } else if (container instanceof JSONObject) {
JSONObject document = getDocument(container); JSONObject document = toDocument(container);
if (!document.containsKey(field)) { if (!document.containsKey(fragment.value())) {
throw new InvalidPathException(); throw new InvalidPathException("Invalid path element: " + currentPath + " <==");
} }
result = document.get(field); result = document.get(fragment.value());
} else { } else {
throw new UnsupportedOperationException("can not get value from " + container.getClass().getName()); throw new InvalidPathException("Invalid path element: " + currentPath + " <==");
} }
//notNull(result, "invalid path: " + field);
return result; return result;
} }
} }

3
json-assert/src/test/java/com/jayway/jsonassert/JSONReaderTest.java

@ -93,6 +93,9 @@ public class JSONReaderTest {
@Test @Test
public void a_path_can_be_checked_for_non_existence() throws Exception { public void a_path_can_be_checked_for_non_existence() throws Exception {
JSONReader reader = JSONAssert.parse(TEST_DEEP_PATH_DOCUMENT); JSONReader reader = JSONAssert.parse(TEST_DEEP_PATH_DOCUMENT);
assertFalse(reader.hasJsonPath("a.b.c.FOO")); assertFalse(reader.hasJsonPath("a.b.c.FOO"));

42
json-assert/src/test/resources/json-test-doc.json

@ -1,18 +1,30 @@
{ {
"id": 100, "id": 100,
"type": "donut", "type": "donut",
"name": "Cake", "name": "Cake",
"available": true, "available": true,
"ppu": 0.55, "ppu": 0.55,
"batters": "batters":
{ {
"batter": "batter":
[ [
{ "id": "1001", "type": "Regular" }, {
{ "id": "1002", "type": "Chocolate" }, "id": "1001",
{ "id": "1003", "type": "Blueberry" }, "type": "Regular"
{ "id": "1004", "type": "Devil's Food" } },
] {
}, "id": "1002",
"toppings": ["Glazed", "Sugar", "Chocolate", "Maple"] "type": "Chocolate"
},
{
"id": "1003",
"type": "Blueberry"
},
{
"id": "1004",
"type": "Devil's Food"
}
]
},
"toppings": ["Glazed", "Sugar", "Chocolate", "Maple"]
} }
Loading…
Cancel
Save