Browse Source

Fixed issue with indefinite path throwing exception.

pull/57/head
Kalle Stenflo 10 years ago
parent
commit
393926ad96
  1. 26
      json-path/src/main/java/com/jayway/jsonpath/Option.java
  2. 31
      json-path/src/main/java/com/jayway/jsonpath/internal/token/PathToken.java
  3. 3
      json-path/src/main/java/com/jayway/jsonpath/internal/token/WildcardPathToken.java
  4. 21
      json-path/src/test/java/com/jayway/jsonpath/OptionsTest.java
  5. 26
      json-path/src/test/java/com/jayway/jsonpath/old/IssuesTest.java
  6. 81
      json-path/src/test/java/com/jayway/jsonpath/old/JsonPathTest.java
  7. 2
      json-path/src/test/java/com/jayway/jsonpath/old/JsonProviderTest.java
  8. 44
      json-path/src/test/java/com/jayway/jsonpath/old/MultiAttributeTest.java

26
json-path/src/main/java/com/jayway/jsonpath/Option.java

@ -58,7 +58,31 @@ public enum Option {
* If an exception is thrown and the option {@link Option#ALWAYS_RETURN_LIST} an empty list is returned.
* If an exception is thrown and the option {@link Option#ALWAYS_RETURN_LIST} is not present null is returned.
*/
SUPPRESS_EXCEPTIONS
SUPPRESS_EXCEPTIONS,
/**
* Configures JsonPath to require properties defined in path when an <bold>indefinite</bold> path is evaluated.
*
*
* Given:
*
* <pre>
* [
* {
* "a" : "a-val",
* "b" : "b-val"
* },
* {
* "a" : "a-val",
* }
* ]
* </pre>
*
* evaluating the path "$[*].b"
*
* If REQUIRE_PATH_PROPERTIES option is present PathNotFoundException is thrown.
* If REQUIRE_PATH_PROPERTIES option is not present ["b-val"] is returned.
*/
REQUIRE_PATH_PROPERTIES
}

31
json-path/src/main/java/com/jayway/jsonpath/internal/token/PathToken.java

@ -24,11 +24,14 @@ import java.util.List;
public abstract class PathToken {
private PathToken prev;
private PathToken next;
private Boolean definite = null;
private Boolean upstreamDefinite = null;
PathToken appendTailToken(PathToken next) {
this.next = next;
this.next.prev = this;
return next;
}
@ -43,7 +46,7 @@ public abstract class PathToken {
if(ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)){
propertyVal = null;
} else {
if(ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)){
if(ctx.options().contains(Option.SUPPRESS_EXCEPTIONS) && !ctx.options().contains(Option.REQUIRE_PATH_PROPERTIES)){
return;
} else {
throw new PathNotFoundException("No results for path: " + evalPath);
@ -51,7 +54,13 @@ public abstract class PathToken {
}
} else {
throw new PathNotFoundException();
if(!isUpstreamDefinite() &&
!ctx.options().contains(Option.REQUIRE_PATH_PROPERTIES) &&
!ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)){
return;
} else {
throw new PathNotFoundException(evalPath);
}
}
}
if (isLeaf()) {
@ -109,6 +118,9 @@ public abstract class PathToken {
}
}
PathToken prev(){
return prev;
}
PathToken next() {
if (isLeaf()) {
@ -121,6 +133,21 @@ public abstract class PathToken {
return next == null;
}
boolean isRoot() {
return prev == null;
}
boolean isUpstreamDefinite(){
if(upstreamDefinite != null){
return upstreamDefinite.booleanValue();
}
boolean isUpstreamDefinite = isTokenDefinite();
if (isUpstreamDefinite && !isRoot()) {
isUpstreamDefinite = prev.isPathDefinite();
}
upstreamDefinite = isUpstreamDefinite;
return isUpstreamDefinite;
}
public int getTokenCount() {
int cnt = 1;

3
json-path/src/main/java/com/jayway/jsonpath/internal/token/WildcardPathToken.java

@ -14,6 +14,7 @@
*/
package com.jayway.jsonpath.internal.token;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
import static java.util.Arrays.asList;
@ -34,7 +35,7 @@ public class WildcardPathToken extends PathToken {
try {
handleArrayIndex(idx, currentPath, model, ctx);
} catch (PathNotFoundException p){
if(!isLeaf() && !next().isLeaf()){
if(ctx.options().contains(Option.REQUIRE_PATH_PROPERTIES)){
throw p;
}
}

21
json-path/src/test/java/com/jayway/jsonpath/OptionsTest.java

@ -2,13 +2,17 @@ package com.jayway.jsonpath;
import org.junit.Test;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.jayway.jsonpath.JsonPath.using;
import static com.jayway.jsonpath.Option.*;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class OptionsTest extends BaseTest {
@ -76,4 +80,21 @@ public class OptionsTest extends BaseTest {
assertThat((List)result).containsOnly("a", "b");
}
@Test
public void when_property_is_required_exception_is_thrown() {
List<Map<String, String>> model = asList(singletonMap("a", "a-val"),singletonMap("b", "b-val"));
Configuration conf = Configuration.defaultConfiguration();
assertThat(using(conf).parse(model).read("$[*].a", List.class)).containsExactly("a-val");
conf = conf.addOptions(Option.REQUIRE_PATH_PROPERTIES);
try{
using(conf).parse(model).read("$[*].a", List.class);
fail("Should throw PathNotFoundException");
} catch (PathNotFoundException pnf){}
}
}

26
json-path/src/test/java/com/jayway/jsonpath/old/IssuesTest.java

@ -163,12 +163,9 @@ public class IssuesTest {
" }\n" +
"]";
List<Double> result = read(json, "$.[?(@.compatible == true)].sku");
List<String> result = read(json, "$.[?(@.compatible == true)].sku");
System.out.println(result);
//assertThat(result.getValue(0), is(new Double(10.1)));
//assertThat(result.getValue(1), is(new Double(21.0)));
Assertions.assertThat(result).containsExactly("SKU-005", "SKU-003");
}
@ -326,8 +323,8 @@ public class IssuesTest {
List<Map<String, Object>> result = read(json, "$.store.book[?(@.author.age == 36)]");
System.out.println(result);
Assertions.assertThat(result).hasSize(1);
Assertions.assertThat(result.get(0)).containsEntry("title", "Sayings of the Century");
}
@Test
@ -429,6 +426,21 @@ public class IssuesTest {
} catch (PathNotFoundException e){
Assertions.assertThat(e).hasMessage("No results for path: $['a']['x']");
}
}
@Test
public void issue_x() {
String json = "{\n" +
" \"a\" : [\n" +
" {},\n" +
" { \"b\" : [ { \"c\" : \"foo\"} ] }\n" +
" ]\n" +
"}\n";
List<String> result = JsonPath.read(json, "$.a.*.b.*.c");
Assertions.assertThat(result).containsExactly("foo");
}
}

81
json-path/src/test/java/com/jayway/jsonpath/old/JsonPathTest.java

@ -3,6 +3,7 @@ package com.jayway.jsonpath.old;
import com.jayway.jsonpath.BaseTest;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.PathCompiler;
import org.assertj.core.api.Assertions;
@ -55,7 +56,7 @@ public class JsonPathTest extends BaseTest {
" \"display-price\": 19.95,\n" +
" \"foo:bar\": \"fooBar\",\n" +
" \"dot.notation\": \"new\",\n" +
" \"dash-notation\": \"dashes\"\n" +
" \"dash-notation\": \"dashes\"\n" +
" }\n" +
" }\n" +
"}";
@ -84,8 +85,7 @@ public class JsonPathTest extends BaseTest {
//Object read = JsonPath.using(Configuration.defaultConfiguration().setOptions(Option.THROW_ON_MISSING_PROPERTY)).parse(DOCUMENT).read("$.store.book[*].fooBar");
//Object read = JsonPath.using(Configuration.defaultConfiguration()).parse(DOCUMENT).read("$.store.book[*].fooBar");
Object read2 = JsonPath.using(Configuration.defaultConfiguration()).parse(DOCUMENT).read("$.store.book[*].fooBar.not");
Object read2 = JsonPath.using(Configuration.defaultConfiguration().addOptions(Option.REQUIRE_PATH_PROPERTIES)).parse(DOCUMENT).read("$.store.book[*].fooBar.not");
}
@ -127,20 +127,16 @@ public class JsonPathTest extends BaseTest {
" },\n" +
" \"version\": 1371160528774\n" +
"}";
// System.out.println(JsonPath.read(json, "$.data.passes[0].id"));
System.out.println(JsonPath.isPathDefinite("$.data.passes[0].id"));
System.out.println(JsonPath.read(json, "$.data2.passes[0].id"));
System.out.println(JsonPath.isPathDefinite("$.data2.passes[0].id"));
try {
JsonPath.read(json, "$.data.passes[0].id");
Assertions.fail("Expected PathNotFoundException");
} catch (PathNotFoundException e) {
}
Assertions.assertThat(JsonPath.read(json, "$.data2.passes[0].id")).isEqualTo("1");
}
@Test public void array_start_expands() throws Exception {
@Test
public void array_start_expands() throws Exception {
//assertThat(JsonPath.<List<String>>read(ARRAY_EXPAND, "$[?(@.parent = 'ONE')].child.name"), hasItems("NAME_ONE"));
assertThat(JsonPath.<List<String>>read(ARRAY_EXPAND, "$[?(@['parent'] == 'ONE')].child.name"), hasItems("NAME_ONE"));
}
@ -148,19 +144,16 @@ public class JsonPathTest extends BaseTest {
@Test
public void bracket_notation_can_be_used_in_path() throws Exception {
//System.out.println(ScriptEngineJsonPath.eval(DOCUMENT, "$.['store'].['bicycle'].['dot.notation']"));
assertEquals("new", JsonPath.read(DOCUMENT, "$.['store'].bicycle.['dot.notation']"));
assertEquals("new", JsonPath.read(DOCUMENT, "$['store']['bicycle']['dot.notation']"));
assertEquals("new", JsonPath.read(DOCUMENT, "$.['store']['bicycle']['dot.notation']"));
assertEquals("new", JsonPath.read(DOCUMENT, "$.['store'].['bicycle'].['dot.notation']"));
assertEquals("dashes", JsonPath.read(DOCUMENT, "$.['store'].bicycle.['dash-notation']"));
assertEquals("dashes", JsonPath.read(DOCUMENT, "$['store']['bicycle']['dash-notation']"));
assertEquals("dashes", JsonPath.read(DOCUMENT, "$.['store']['bicycle']['dash-notation']"));
assertEquals("dashes", JsonPath.read(DOCUMENT, "$.['store'].['bicycle'].['dash-notation']"));
assertEquals("dashes", JsonPath.read(DOCUMENT, "$.['store'].bicycle.['dash-notation']"));
assertEquals("dashes", JsonPath.read(DOCUMENT, "$['store']['bicycle']['dash-notation']"));
assertEquals("dashes", JsonPath.read(DOCUMENT, "$.['store']['bicycle']['dash-notation']"));
assertEquals("dashes", JsonPath.read(DOCUMENT, "$.['store'].['bicycle'].['dash-notation']"));
}
@Test
@ -168,7 +161,6 @@ public class JsonPathTest extends BaseTest {
List<Object> matches = JsonPath.read(ARRAY, "$.[?(@.value == 1)]");
assertEquals(1, matches.size());
System.out.println(matches);
}
@Test
@ -176,13 +168,10 @@ public class JsonPathTest extends BaseTest {
Integer matches = JsonPath.read(ARRAY, "$.[1].value");
assertEquals(new Integer(2), matches);
System.out.println(matches);
}
@Test
public void read_path_with_colon() throws Exception {
//TODO: breaking v2
//assertEquals(JsonPath.read(DOCUMENT, "$.store.bicycle.foo:bar"), "fooBar");
assertEquals(JsonPath.read(DOCUMENT, "$['store']['bicycle']['foo:bar']"), "fooBar");
}
@ -209,6 +198,7 @@ public class JsonPathTest extends BaseTest {
JsonPath path = JsonPath.compile("$.store.book[*]");
List<Object> list = path.read(DOCUMENT);
Assertions.assertThat(list.size()).isEqualTo(4);
}
@ -244,31 +234,24 @@ public class JsonPathTest extends BaseTest {
@Test
public void all_prices_in_store() throws Exception {
assertThat(JsonPath.<List<Double>>read(DOCUMENT, "$.store..['display-price']"), hasItems(8.95D, 12.99D, 8.99D, 19.95D));
}
@Test
public void access_array_by_index_from_tail() throws Exception {
//TODO: breaking change
//assertThat(JsonPath.<String>read(DOCUMENT, "$..book[(@.length-1)].author"), equalTo("J. R. R. Tolkien"));
//assertThat(JsonPath.<String>read(DOCUMENT, "$..book[1:].author"), equalTo("J. R. R. Tolkien"));
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$..book[(@.length-1)].author"), hasItems("J. R. R. Tolkien"));
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$..book[1:].author"), hasItems("Evelyn Waugh","Herman Melville","J. R. R. Tolkien"));
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$..book[1:].author"), hasItems("Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"));
}
@Test
public void read_store_book_index_0_and_1() throws Exception {
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$.store.book[0,1].author"), hasItems("Nigel Rees", "Evelyn Waugh"));
assertTrue(JsonPath.<List>read(DOCUMENT, "$.store.book[0,1].author").size() == 2);
}
@Test
public void read_store_book_pull_first_2() throws Exception {
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$.store.book[:2].author"), hasItems("Nigel Rees", "Evelyn Waugh"));
assertTrue(JsonPath.<List>read(DOCUMENT, "$.store.book[:2].author").size() == 2);
}
@ -276,52 +259,36 @@ public class JsonPathTest extends BaseTest {
@Test
public void read_store_book_filter_by_isbn() throws Exception {
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$.store.book[?(@.isbn)].isbn"), hasItems("0-553-21311-3", "0-395-19395-8"));
assertTrue(JsonPath.<List>read(DOCUMENT, "$.store.book[?(@.isbn)].isbn").size() == 2);
assertTrue(JsonPath.<List>read(DOCUMENT, "$.store.book[?(@['isbn'])].isbn").size() == 2);
assertTrue(JsonPath.<List>read(DOCUMENT, "$.store.book[?(@['isbn'])].isbn").size() == 2);
}
@Test
public void all_books_cheaper_than_10() throws Exception {
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$..book[?(@['display-price'] < 10)].title"), hasItems("Sayings of the Century", "Moby Dick"));
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$..book[?(@.display-price < 10)].title"), hasItems("Sayings of the Century", "Moby Dick"));
}
@Test
@Test
public void all_books() throws Exception {
//List<String> books = JsonPath.<List<String>>read(DOCUMENT, "$..book");
Object books = JsonPath.<List<String>>read(DOCUMENT, "$..book");
System.out.println(books);
}
Assertions.assertThat(JsonPath.<List<Object>>read(DOCUMENT, "$..book")).hasSize(1);
}
@Test
public void dot_in_predicate_works() throws Exception {
assertThat(JsonPath.<List<String>>read(PRODUCT_JSON, "$.product[?(@.version=='4.0')].codename"), hasItems("Montreal"));
}
@Test
public void dots_in_predicate_works() throws Exception {
assertThat(JsonPath.<List<String>>read(PRODUCT_JSON, "$.product[?(@.['attr.with.dot']=='A')].codename"), hasItems("Seattle"));
//assertThat(JsonPath.<List<String>>read(PRODUCT_JSON, "$.product[?(@.attr.with.dot=='A')].codename"), hasItems("Seattle"));
}
@Test
public void all_books_with_category_reference() throws Exception {
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$..book[?(@.category=='reference')].title"), hasItems("Sayings of the Century"));
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$.store.book[?(@.category=='reference')].title"), hasItems("Sayings of the Century"));
}
@Test
@ -331,15 +298,11 @@ public class JsonPathTest extends BaseTest {
@Test(expected = PathNotFoundException.class)
public void access_index_out_of_bounds_does_not_throw_exception() throws Exception {
Object res = JsonPath.read(DOCUMENT, "$.store.book[100].author");
JsonPath.read(DOCUMENT, "$.store.book[100].author");
}
@Test
public void exists_filter_with_nested_path() throws Exception {
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$..[?(@.bicycle.color)]"), hasSize(1));
assertThat(JsonPath.<List<String>>read(DOCUMENT, "$..[?(@.bicycle.numberOfGears)]"), hasSize(0));

2
json-path/src/test/java/com/jayway/jsonpath/old/JsonProviderTest.java

@ -54,7 +54,6 @@ public class JsonProviderTest {
Object o = provider.parse(DOCUMENT);
System.out.println(o);
}
@ -64,6 +63,5 @@ public class JsonProviderTest {
Object o = provider.parse(ARRAY);
System.out.println(o);
}
}

44
json-path/src/test/java/com/jayway/jsonpath/old/MultiAttributeTest.java

@ -1,44 +0,0 @@
package com.jayway.jsonpath.old;
public class MultiAttributeTest {
public final static String DOCUMENT =
"{ \"store\": {\n" +
" \"book\": [ \n" +
" { \"category\": \"reference\",\n" +
" \"author\": \"Nigel Rees\",\n" +
" \"title\": \"Sayings of the Century\",\n" +
" \"display-price\": 8.95\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Evelyn Waugh\",\n" +
" \"title\": \"Sword of Honour\",\n" +
" \"display-price\": 12.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Herman Melville\",\n" +
" \"title\": \"Moby Dick\",\n" +
" \"isbn\": \"0-553-21311-3\",\n" +
" \"display-price\": 8.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"J. R. R. Tolkien\",\n" +
" \"title\": \"The Lord of the Rings\",\n" +
" \"isbn\": \"0-395-19395-8\",\n" +
" \"display-price\": 22.99\n" +
" }\n" +
" ],\n" +
" \"bicycle\": {\n" +
" \"color\": \"red\",\n" +
" \"display-price\": 19.95,\n" +
" \"foo:bar\": \"fooBar\",\n" +
" \"dot.notation\": \"new\",\n" +
" \"dash-notation\": \"dashes\"\n" +
" }\n" +
" }\n" +
"}";
}
Loading…
Cancel
Save