diff --git a/json-assert/src/main/java/com/jayway/jsonassert/InvalidPathException.java b/json-assert/src/main/java/com/jayway/jsonassert/InvalidPathException.java index 24670271..fc9d27cb 100644 --- a/json-assert/src/main/java/com/jayway/jsonassert/InvalidPathException.java +++ b/json-assert/src/main/java/com/jayway/jsonassert/InvalidPathException.java @@ -6,4 +6,19 @@ package com.jayway.jsonassert; * Time: 10:09 AM */ 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); + } } diff --git a/json-assert/src/main/java/com/jayway/jsonassert/impl/JSONPathFragment.java b/json-assert/src/main/java/com/jayway/jsonassert/impl/JSONPathFragment.java index 60be55b9..0def3f30 100644 --- a/json-assert/src/main/java/com/jayway/jsonassert/impl/JSONPathFragment.java +++ b/json-assert/src/main/java/com/jayway/jsonassert/impl/JSONPathFragment.java @@ -22,10 +22,31 @@ class JSONPathFragment { this.fragment = fragment; } - String fragment() { + String value() { 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() { return ARRAY_POSITION_PATTER.matcher(fragment).matches() || GROOVY_POSITION_PATTER.matcher(fragment).matches(); } diff --git a/json-assert/src/main/java/com/jayway/jsonassert/impl/JSONReaderImpl.java b/json-assert/src/main/java/com/jayway/jsonassert/impl/JSONReaderImpl.java index e3acd523..59dca68c 100644 --- a/json-assert/src/main/java/com/jayway/jsonassert/impl/JSONReaderImpl.java +++ b/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 Object root; + private String currentPath; public static synchronized JSONReader parse(Reader reader) throws java.text.ParseException, IOException { @@ -130,27 +131,32 @@ public class JSONReaderImpl implements JSONReader { private T getByPath(Class clazz, String stringPath) { + currentPath = ""; Object current = this.root; JSONPath path = new JSONPath(stringPath); while (path.hasMoreFragments()) { + JSONPathFragment fragment = path.nextFragment(); + + currentPath = fragment.appendToPath(currentPath); + if (fragment.isArrayIndex()) { - current = getArray(current).get(fragment.getArrayIndex()); + current = toArray(current).get(fragment.getArrayIndex()); } else if (fragment.isArrayWildcard()) { - current = getContainerValue(current, path.nextFragment().fragment()); + current = getContainerValue(current, path.nextFragment()); } else { - current = getContainerValue(current, fragment.fragment()); + current = getContainerValue(current, fragment); } } return clazz.cast(current); } - private JSONArray getArray(Object array) { + private JSONArray toArray(Object array) { return (JSONArray) array; } - private JSONObject getDocument(Object document) { + private JSONObject toDocument(Object document) { return (JSONObject) document; } @@ -161,32 +167,30 @@ public class JSONReaderImpl implements JSONReader { * will be returned in a List * * @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 */ - private Object getContainerValue(Object container, Object field) { + private Object getContainerValue(Object container, JSONPathFragment fragment) { Object result; if (container instanceof JSONArray) { List list = new LinkedList(); - for (Object doc : getArray(container)) { - list.add(getContainerValue(doc, field)); + for (Object doc : toArray(container)) { + list.add(getContainerValue(doc, fragment)); } result = list; } else if (container instanceof JSONObject) { - JSONObject document = getDocument(container); + JSONObject document = toDocument(container); - if (!document.containsKey(field)) { - throw new InvalidPathException(); + if (!document.containsKey(fragment.value())) { + throw new InvalidPathException("Invalid path element: " + currentPath + " <=="); } - result = document.get(field); + result = document.get(fragment.value()); } 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; } } diff --git a/json-assert/src/test/java/com/jayway/jsonassert/JSONReaderTest.java b/json-assert/src/test/java/com/jayway/jsonassert/JSONReaderTest.java index 1508a621..fa46084e 100644 --- a/json-assert/src/test/java/com/jayway/jsonassert/JSONReaderTest.java +++ b/json-assert/src/test/java/com/jayway/jsonassert/JSONReaderTest.java @@ -93,6 +93,9 @@ public class JSONReaderTest { @Test public void a_path_can_be_checked_for_non_existence() throws Exception { + + + JSONReader reader = JSONAssert.parse(TEST_DEEP_PATH_DOCUMENT); assertFalse(reader.hasJsonPath("a.b.c.FOO")); diff --git a/json-assert/src/test/resources/json-test-doc.json b/json-assert/src/test/resources/json-test-doc.json index 24ea2a54..f03e2897 100644 --- a/json-assert/src/test/resources/json-test-doc.json +++ b/json-assert/src/test/resources/json-test-doc.json @@ -1,18 +1,30 @@ { - "id": 100, - "type": "donut", - "name": "Cake", + "id": 100, + "type": "donut", + "name": "Cake", "available": true, - "ppu": 0.55, - "batters": - { - "batter": - [ - { "id": "1001", "type": "Regular" }, - { "id": "1002", "type": "Chocolate" }, - { "id": "1003", "type": "Blueberry" }, - { "id": "1004", "type": "Devil's Food" } - ] - }, - "toppings": ["Glazed", "Sugar", "Chocolate", "Maple"] + "ppu": 0.55, + "batters": + { + "batter": + [ + { + "id": "1001", + "type": "Regular" + }, + { + "id": "1002", + "type": "Chocolate" + }, + { + "id": "1003", + "type": "Blueberry" + }, + { + "id": "1004", + "type": "Devil's Food" + } + ] + }, + "toppings": ["Glazed", "Sugar", "Chocolate", "Maple"] } \ No newline at end of file