Browse Source

multiple properties path token at the end of the path: tests and fix

pull/142/head
Alexey Makeyev 9 years ago
parent
commit
e8af47fa98
  1. 31
      json-path/src/main/java/com/jayway/jsonpath/internal/token/ScanPathToken.java
  2. 30
      json-path/src/test/java/com/jayway/jsonpath/DeepScanTest.java
  3. 4
      json-path/src/test/java/com/jayway/jsonpath/MultiPropTest.java

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

@ -167,16 +167,29 @@ public class ScanPathToken extends PathToken {
@Override @Override
public boolean matches(Object model) { public boolean matches(Object model) {
if (ctx.jsonProvider().isMap(model)) { if (! ctx.jsonProvider().isMap(model)) {
if (ctx.options().contains(Option.REQUIRE_PROPERTIES)) { return false;
// Have to require properties defined in path when an indefinite path is evaluated,
// so have to go there and search for it.
return true;
}
Collection<String> keys = ctx.jsonProvider().getPropertyKeys(model);
return keys.containsAll(propertyPathToken.getProperties());
} }
return false;
if (ctx.options().contains(Option.REQUIRE_PROPERTIES)) {
// Have to require properties defined in path when an indefinite path is evaluated,
// so have to go there and search for it.
return true;
}
if (! propertyPathToken.isTokenDefinite()) {
// It's responsibility of PropertyPathToken code to handle indefinite scenario of properties,
// so we'll allow it to do its job.
return true;
}
if (ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)) {
// In case of DEFAULT_PATH_LEAF_TO_NULL missing properties is not a problem.
return true;
}
Collection<String> keys = ctx.jsonProvider().getPropertyKeys(model);
return keys.containsAll(propertyPathToken.getProperties());
} }
} }
} }

30
json-path/src/test/java/com/jayway/jsonpath/DeepScanTest.java

@ -2,10 +2,14 @@ package com.jayway.jsonpath;
import org.junit.Test; import org.junit.Test;
import static com.jayway.jsonpath.JsonPath.using;
import static com.jayway.jsonpath.TestUtils.assertEvaluationThrows; import static com.jayway.jsonpath.TestUtils.assertEvaluationThrows;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import java.util.Map;
/** /**
* Deep scan is indefinite, so certain "illegal" actions become a no-op instead of a path evaluation exception. * Deep scan is indefinite, so certain "illegal" actions become a no-op instead of a path evaluation exception.
*/ */
@ -84,5 +88,31 @@ public class DeepScanTest extends BaseTest {
// foo.bar must be found in every object node after deep scan (which is impossible) // foo.bar must be found in every object node after deep scan (which is impossible)
assertEvaluationThrows("{\"foo\": {\"bar\": 4}}", "$..foo.bar", PathNotFoundException.class, conf); assertEvaluationThrows("{\"foo\": {\"bar\": 4}}", "$..foo.bar", PathNotFoundException.class, conf);
assertEvaluationThrows("{\"foo\": {\"bar\": 4}, \"baz\": 2}", "$..['foo', 'baz']", PathNotFoundException.class, conf);
}
@Test
public void when_deep_scanning_leaf_multi_props_work() {
Object result = JsonPath.parse("[{\"a\": \"a-val\", \"b\": \"b-val\", \"c\": \"c-val\"}, [1, 5], {\"a\": \"a-val\"}]").read(
"$..['a', 'c']");
// This is current deep scan semantics: only objects containing all properties specified in multiprops token are
// considered.
assertThat(result).asList().hasSize(1);
result = ((List)result).get(0);
assertThat(result).isInstanceOf(Map.class);
assertThat((Map)result).hasSize(2).containsEntry("a", "a-val").containsEntry("c", "c-val");
// But this semantics changes when DEFAULT_PATH_LEAF_TO_NULL comes into play.
Configuration conf = Configuration.defaultConfiguration().addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL);
result = using(conf).parse("[{\"a\": \"a-val\", \"b\": \"b-val\", \"c\": \"c-val\"}, [1, 5], {\"a\": \"a-val\"}]").read(
"$..['a', 'c']");
// todo: deep equality test, but not tied to any json provider
assertThat(result).asList().hasSize(2);
for (final Object node : (List)result) {
assertThat(node).isInstanceOf(Map.class);
assertThat((Map)node).hasSize(2).containsEntry("a", "a-val");
}
} }
} }

4
json-path/src/test/java/com/jayway/jsonpath/MultiPropTest.java

@ -24,6 +24,10 @@ public class MultiPropTest {
assertThat(using(conf).parse(model).read("$['a', 'b']", Map.class)) assertThat(using(conf).parse(model).read("$['a', 'b']", Map.class))
.containsEntry("a", "a-val") .containsEntry("a", "a-val")
.containsEntry("b", "b-val"); .containsEntry("b", "b-val");
// current semantics: absent props are skipped
assertThat(using(conf).parse(model).read("$['a', 'd']", Map.class))
.hasSize(1).containsEntry("a", "a-val");
} }
@Test @Test

Loading…
Cancel
Save